Remove ParsedURLString
[WebKit-https.git] / Source / WebCore / loader / FrameLoader.cpp
1 /*
2  * Copyright (C) 2006-2018 Apple Inc. All rights reserved.
3  * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
4  * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
5  * Copyright (C) 2008 Alp Toker <alp@atoker.com>
6  * Copyright (C) Research In Motion Limited 2009. All rights reserved.
7  * Copyright (C) 2011 Kris Jordan <krisjordan@gmail.com>
8  * Copyright (C) 2011 Google Inc. All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  *
14  * 1.  Redistributions of source code must retain the above copyright
15  *     notice, this list of conditions and the following disclaimer.
16  * 2.  Redistributions in binary form must reproduce the above copyright
17  *     notice, this list of conditions and the following disclaimer in the
18  *     documentation and/or other materials provided with the distribution.
19  * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
20  *     its contributors may be used to endorse or promote products derived
21  *     from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
24  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
27  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34
35 #include "config.h"
36 #include "FrameLoader.h"
37
38 #include "AXObjectCache.h"
39 #include "ApplicationCacheHost.h"
40 #include "BackForwardController.h"
41 #include "BeforeUnloadEvent.h"
42 #include "CachedPage.h"
43 #include "CachedResourceLoader.h"
44 #include "Chrome.h"
45 #include "ChromeClient.h"
46 #include "CommonVM.h"
47 #include "ContentFilter.h"
48 #include "ContentSecurityPolicy.h"
49 #include "DOMWindow.h"
50 #include "DatabaseManager.h"
51 #include "DiagnosticLoggingClient.h"
52 #include "DiagnosticLoggingKeys.h"
53 #include "Document.h"
54 #include "DocumentLoader.h"
55 #include "Editor.h"
56 #include "EditorClient.h"
57 #include "Element.h"
58 #include "Event.h"
59 #include "EventHandler.h"
60 #include "EventNames.h"
61 #include "FloatRect.h"
62 #include "FormState.h"
63 #include "FormSubmission.h"
64 #include "Frame.h"
65 #include "FrameLoadRequest.h"
66 #include "FrameLoaderClient.h"
67 #include "FrameNetworkingContext.h"
68 #include "FrameTree.h"
69 #include "FrameView.h"
70 #include "GCController.h"
71 #include "HTMLFormElement.h"
72 #include "HTMLInputElement.h"
73 #include "HTMLNames.h"
74 #include "HTMLObjectElement.h"
75 #include "HTMLParserIdioms.h"
76 #include "HTTPHeaderNames.h"
77 #include "HTTPParsers.h"
78 #include "HistoryController.h"
79 #include "HistoryItem.h"
80 #include "IgnoreOpensDuringUnloadCountIncrementer.h"
81 #include "InspectorController.h"
82 #include "InspectorInstrumentation.h"
83 #include "LinkLoader.h"
84 #include "LoadTiming.h"
85 #include "LoaderStrategy.h"
86 #include "Logging.h"
87 #include "MemoryCache.h"
88 #include "MemoryRelease.h"
89 #include "NavigationDisabler.h"
90 #include "NavigationScheduler.h"
91 #include "Page.h"
92 #include "PageCache.h"
93 #include "PageTransitionEvent.h"
94 #include "PerformanceLogging.h"
95 #include "PlatformStrategies.h"
96 #include "PluginData.h"
97 #include "PluginDocument.h"
98 #include "PolicyChecker.h"
99 #include "ProgressTracker.h"
100 #include "ResourceHandle.h"
101 #include "ResourceLoadInfo.h"
102 #include "ResourceLoadObserver.h"
103 #include "ResourceRequest.h"
104 #include "SVGDocument.h"
105 #include "SVGLocatable.h"
106 #include "SVGNames.h"
107 #include "SVGViewElement.h"
108 #include "SVGViewSpec.h"
109 #include "ScriptController.h"
110 #include "ScriptSourceCode.h"
111 #include "ScrollAnimator.h"
112 #include "SecurityOrigin.h"
113 #include "SecurityPolicy.h"
114 #include "SegmentedString.h"
115 #include "SerializedScriptValue.h"
116 #include "Settings.h"
117 #include "ShouldTreatAsContinuingLoad.h"
118 #include "SubframeLoader.h"
119 #include "SubresourceLoader.h"
120 #include "TextResourceDecoder.h"
121 #include "UserContentController.h"
122 #include "UserGestureIndicator.h"
123 #include "WindowFeatures.h"
124 #include "XMLDocumentParser.h"
125 #include <dom/ScriptDisallowedScope.h>
126 #include <wtf/CompletionHandler.h>
127 #include <wtf/Ref.h>
128 #include <wtf/SetForScope.h>
129 #include <wtf/StdLibExtras.h>
130 #include <wtf/SystemTracing.h>
131 #include <wtf/text/CString.h>
132 #include <wtf/text/WTFString.h>
133
134 #if ENABLE(WEB_ARCHIVE) || ENABLE(MHTML)
135 #include "Archive.h"
136 #endif
137
138 #if ENABLE(DATA_DETECTION)
139 #include "DataDetection.h"
140 #endif
141
142 #if PLATFORM(IOS)
143 #include "DocumentType.h"
144 #include "ResourceLoader.h"
145 #include "RuntimeApplicationChecks.h"
146 #include "WKContentObservation.h"
147 #endif
148
149 #define RELEASE_LOG_IF_ALLOWED(fmt, ...) RELEASE_LOG_IF(isAlwaysOnLoggingAllowed(), Network, "%p - FrameLoader::" fmt, this, ##__VA_ARGS__)
150
151 namespace WebCore {
152
153 using namespace HTMLNames;
154 using namespace SVGNames;
155
156 static const char defaultAcceptHeader[] = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
157
158 bool isBackForwardLoadType(FrameLoadType type)
159 {
160     switch (type) {
161     case FrameLoadType::Standard:
162     case FrameLoadType::Reload:
163     case FrameLoadType::ReloadFromOrigin:
164     case FrameLoadType::ReloadExpiredOnly:
165     case FrameLoadType::Same:
166     case FrameLoadType::RedirectWithLockedBackForwardList:
167     case FrameLoadType::Replace:
168         return false;
169     case FrameLoadType::Back:
170     case FrameLoadType::Forward:
171     case FrameLoadType::IndexedBackForward:
172         return true;
173     }
174     ASSERT_NOT_REACHED();
175     return false;
176 }
177
178 bool isReload(FrameLoadType type)
179 {
180     switch (type) {
181     case FrameLoadType::Reload:
182     case FrameLoadType::ReloadFromOrigin:
183     case FrameLoadType::ReloadExpiredOnly:
184         return true;
185     case FrameLoadType::Standard:
186     case FrameLoadType::Same:
187     case FrameLoadType::RedirectWithLockedBackForwardList:
188     case FrameLoadType::Replace:
189     case FrameLoadType::Back:
190     case FrameLoadType::Forward:
191     case FrameLoadType::IndexedBackForward:
192         return false;
193     }
194     ASSERT_NOT_REACHED();
195     return false;
196 }
197
198 // This is not in the FrameLoader class to emphasize that it does not depend on
199 // private FrameLoader data, and to avoid increasing the number of public functions
200 // with access to private data.  Since only this .cpp file needs it, making it
201 // non-member lets us exclude it from the header file, thus keeping FrameLoader.h's
202 // API simpler.
203 //
204 static bool isDocumentSandboxed(Frame& frame, SandboxFlags mask)
205 {
206     return frame.document() && frame.document()->isSandboxed(mask);
207 }
208
209 struct ForbidPromptsScope {
210     ForbidPromptsScope(Page* page) : m_page(page)
211     {
212         if (!m_page)
213             return;
214         m_page->forbidPrompts();
215     }
216
217     ~ForbidPromptsScope()
218     {
219         if (!m_page)
220             return;
221         m_page->allowPrompts();
222     }
223
224     Page* m_page;
225 };
226
227 class FrameLoader::FrameProgressTracker {
228     WTF_MAKE_FAST_ALLOCATED;
229 public:
230     explicit FrameProgressTracker(Frame& frame)
231         : m_frame(frame)
232         , m_inProgress(false)
233     {
234     }
235
236     ~FrameProgressTracker()
237     {
238         if (m_inProgress && m_frame.page())
239             m_frame.page()->progress().progressCompleted(m_frame);
240     }
241
242     void progressStarted()
243     {
244         ASSERT(m_frame.page());
245         if (!m_inProgress)
246             m_frame.page()->progress().progressStarted(m_frame);
247         m_inProgress = true;
248     }
249
250     void progressCompleted()
251     {
252         ASSERT(m_inProgress);
253         ASSERT(m_frame.page());
254         m_inProgress = false;
255         m_frame.page()->progress().progressCompleted(m_frame);
256
257         if (auto pageID = m_frame.loader().client().pageID())
258             platformStrategies()->loaderStrategy()->pageLoadCompleted(pageID.value());
259     }
260
261 private:
262     Frame& m_frame;
263     bool m_inProgress;
264 };
265
266 FrameLoader::FrameLoader(Frame& frame, FrameLoaderClient& client)
267     : m_frame(frame)
268     , m_client(client)
269     , m_policyChecker(std::make_unique<PolicyChecker>(frame))
270     , m_history(std::make_unique<HistoryController>(frame))
271     , m_notifier(frame)
272     , m_subframeLoader(std::make_unique<SubframeLoader>(frame))
273     , m_mixedContentChecker(frame)
274     , m_state(FrameStateProvisional)
275     , m_loadType(FrameLoadType::Standard)
276     , m_quickRedirectComing(false)
277     , m_sentRedirectNotification(false)
278     , m_inStopAllLoaders(false)
279     , m_isExecutingJavaScriptFormAction(false)
280     , m_didCallImplicitClose(true)
281     , m_wasUnloadEventEmitted(false)
282     , m_isComplete(false)
283     , m_needsClear(false)
284     , m_checkTimer(*this, &FrameLoader::checkTimerFired)
285     , m_shouldCallCheckCompleted(false)
286     , m_shouldCallCheckLoadComplete(false)
287     , m_opener(nullptr)
288     , m_loadingFromCachedPage(false)
289     , m_currentNavigationHasShownBeforeUnloadConfirmPanel(false)
290     , m_loadsSynchronously(false)
291     , m_forcedSandboxFlags(SandboxNone)
292 {
293 }
294
295 FrameLoader::~FrameLoader()
296 {
297     setOpener(nullptr);
298
299     for (auto& frame : m_openedFrames)
300         frame->loader().m_opener = nullptr;
301
302     m_client.frameLoaderDestroyed();
303
304     if (m_networkingContext)
305         m_networkingContext->invalidate();
306 }
307
308 void FrameLoader::init()
309 {
310     // This somewhat odd set of steps gives the frame an initial empty document.
311     setPolicyDocumentLoader(m_client.createDocumentLoader(ResourceRequest(URL({ }, emptyString())), SubstituteData()).ptr());
312     setProvisionalDocumentLoader(m_policyDocumentLoader.get());
313     m_provisionalDocumentLoader->startLoadingMainResource(ShouldContinue::Yes);
314
315     Ref<Frame> protect(m_frame);
316     m_frame.document()->cancelParsing();
317     m_stateMachine.advanceTo(FrameLoaderStateMachine::DisplayingInitialEmptyDocument);
318
319     m_networkingContext = m_client.createNetworkingContext();
320     m_progressTracker = std::make_unique<FrameProgressTracker>(m_frame);
321 }
322
323 void FrameLoader::initForSynthesizedDocument(const URL&)
324 {
325     // FIXME: We need to initialize the document URL to the specified URL. Currently the URL is empty and hence
326     // FrameLoader::checkCompleted() will overwrite the URL of the document to be activeDocumentLoader()->documentURL().
327
328     auto loader = m_client.createDocumentLoader(ResourceRequest(URL({ }, emptyString())), SubstituteData());
329     loader->attachToFrame(m_frame);
330     loader->setResponse(ResourceResponse(URL(), "text/html"_s, 0, String()));
331     loader->setCommitted(true);
332     setDocumentLoader(loader.ptr());
333
334     m_stateMachine.advanceTo(FrameLoaderStateMachine::DisplayingInitialEmptyDocument);
335     m_stateMachine.advanceTo(FrameLoaderStateMachine::DisplayingInitialEmptyDocumentPostCommit);
336     m_stateMachine.advanceTo(FrameLoaderStateMachine::CommittedFirstRealLoad);
337     m_client.transitionToCommittedForNewPage();
338
339     m_didCallImplicitClose = true;
340     m_isComplete = true;
341     m_state = FrameStateComplete;
342     m_needsClear = true;
343
344     m_networkingContext = m_client.createNetworkingContext();
345     m_progressTracker = std::make_unique<FrameProgressTracker>(m_frame);
346 }
347
348 void FrameLoader::setDefersLoading(bool defers)
349 {
350     if (m_documentLoader)
351         m_documentLoader->setDefersLoading(defers);
352     if (m_provisionalDocumentLoader)
353         m_provisionalDocumentLoader->setDefersLoading(defers);
354     if (m_policyDocumentLoader)
355         m_policyDocumentLoader->setDefersLoading(defers);
356     history().setDefersLoading(defers);
357
358     if (!defers) {
359         m_frame.navigationScheduler().startTimer();
360         startCheckCompleteTimer();
361     }
362 }
363
364 void FrameLoader::checkContentPolicy(const ResourceResponse& response, ContentPolicyDecisionFunction&& function)
365 {
366     if (!activeDocumentLoader()) {
367         // Load was cancelled
368         function(PolicyAction::Ignore);
369         return;
370     }
371
372     client().dispatchDecidePolicyForResponse(response, activeDocumentLoader()->request(), WTFMove(function));
373 }
374
375 void FrameLoader::changeLocation(FrameLoadRequest&& request)
376 {
377     urlSelected(WTFMove(request), nullptr);
378 }
379
380 void FrameLoader::urlSelected(const URL& url, const String& passedTarget, Event* triggeringEvent, LockHistory lockHistory, LockBackForwardList lockBackForwardList, ShouldSendReferrer shouldSendReferrer, ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy, std::optional<NewFrameOpenerPolicy> openerPolicy, const AtomicString& downloadAttribute, const SystemPreviewInfo& systemPreviewInfo)
381 {
382     auto* frame = lexicalFrameFromCommonVM();
383     auto initiatedByMainFrame = frame && frame->isMainFrame() ? InitiatedByMainFrame::Yes : InitiatedByMainFrame::Unknown;
384
385     NewFrameOpenerPolicy newFrameOpenerPolicy = openerPolicy.value_or(shouldSendReferrer == NeverSendReferrer ? NewFrameOpenerPolicy::Suppress : NewFrameOpenerPolicy::Allow);
386     urlSelected(FrameLoadRequest(*m_frame.document(), m_frame.document()->securityOrigin(), { url }, passedTarget, lockHistory, lockBackForwardList, shouldSendReferrer, AllowNavigationToInvalidURL::Yes, newFrameOpenerPolicy, shouldOpenExternalURLsPolicy, initiatedByMainFrame, DoNotReplaceDocumentIfJavaScriptURL, downloadAttribute, systemPreviewInfo), triggeringEvent);
387 }
388
389 void FrameLoader::urlSelected(FrameLoadRequest&& frameRequest, Event* triggeringEvent)
390 {
391     Ref<Frame> protect(m_frame);
392
393     if (m_frame.script().executeIfJavaScriptURL(frameRequest.resourceRequest().url(), frameRequest.shouldReplaceDocumentIfJavaScriptURL()))
394         return;
395
396     if (frameRequest.frameName().isEmpty())
397         frameRequest.setFrameName(m_frame.document()->baseTarget());
398
399     addHTTPOriginIfNeeded(frameRequest.resourceRequest(), outgoingOrigin());
400     m_frame.document()->contentSecurityPolicy()->upgradeInsecureRequestIfNeeded(frameRequest.resourceRequest(), ContentSecurityPolicy::InsecureRequestType::Navigation);
401
402     loadFrameRequest(WTFMove(frameRequest), triggeringEvent, { });
403 }
404
405 void FrameLoader::submitForm(Ref<FormSubmission>&& submission)
406 {
407     ASSERT(submission->method() == FormSubmission::Method::Post || submission->method() == FormSubmission::Method::Get);
408
409     // FIXME: Find a good spot for these.
410     ASSERT(!submission->state().sourceDocument().frame() || submission->state().sourceDocument().frame() == &m_frame);
411
412     if (!m_frame.page())
413         return;
414
415     if (submission->action().isEmpty())
416         return;
417
418     if (isDocumentSandboxed(m_frame, SandboxForms)) {
419         // FIXME: This message should be moved off the console once a solution to https://bugs.webkit.org/show_bug.cgi?id=103274 exists.
420         m_frame.document()->addConsoleMessage(MessageSource::Security, MessageLevel::Error, "Blocked form submission to '" + submission->action().stringCenterEllipsizedToLength() + "' because the form's frame is sandboxed and the 'allow-forms' permission is not set.");
421         return;
422     }
423
424     if (protocolIsJavaScript(submission->action())) {
425         if (!m_frame.document()->contentSecurityPolicy()->allowFormAction(URL(submission->action())))
426             return;
427         m_isExecutingJavaScriptFormAction = true;
428         Ref<Frame> protect(m_frame);
429         m_frame.script().executeIfJavaScriptURL(submission->action(), DoNotReplaceDocumentIfJavaScriptURL);
430         m_isExecutingJavaScriptFormAction = false;
431         return;
432     }
433
434     Frame* targetFrame = findFrameForNavigation(submission->target(), &submission->state().sourceDocument());
435     if (!targetFrame) {
436         if (!DOMWindow::allowPopUp(m_frame) && !UserGestureIndicator::processingUserGesture())
437             return;
438
439         // FIXME: targetFrame can be null for two distinct reasons:
440         // 1. The frame was not found by name, so we should try opening a new window.
441         // 2. The frame was found, but navigating it was not allowed, e.g. by HTML5 sandbox or by origin checks.
442         // Continuing form submission makes no sense in the latter case.
443         // There is a repeat check after timer fires, so this is not a correctness issue.
444
445         targetFrame = &m_frame;
446     } else
447         submission->clearTarget();
448
449     if (!targetFrame->page())
450         return;
451
452     // FIXME: We'd like to remove this altogether and fix the multiple form submission issue another way.
453
454     // We do not want to submit more than one form from the same page, nor do we want to submit a single
455     // form more than once. This flag prevents these from happening; not sure how other browsers prevent this.
456     // The flag is reset in each time we start dispatching a new mouse or key down event, and
457     // also in setView since this part may get reused for a page from the back/forward cache.
458     // The form multi-submit logic here is only needed when we are submitting a form that affects this frame.
459
460     // FIXME: Frame targeting is only one of the ways the submission could end up doing something other
461     // than replacing this frame's content, so this check is flawed. On the other hand, the check is hardly
462     // needed any more now that we reset m_submittedFormURL on each mouse or key down event.
463
464     if (m_frame.tree().isDescendantOf(targetFrame)) {
465         if (m_submittedFormURL == submission->requestURL())
466             return;
467         m_submittedFormURL = submission->requestURL();
468     }
469
470     submission->data().generateFiles(m_frame.document());
471     submission->setReferrer(outgoingReferrer());
472     submission->setOrigin(outgoingOrigin());
473
474     targetFrame->navigationScheduler().scheduleFormSubmission(WTFMove(submission));
475 }
476
477 void FrameLoader::stopLoading(UnloadEventPolicy unloadEventPolicy)
478 {
479     if (m_frame.document() && m_frame.document()->parser())
480         m_frame.document()->parser()->stopParsing();
481
482     if (unloadEventPolicy != UnloadEventPolicyNone)
483         dispatchUnloadEvents(unloadEventPolicy);
484
485     m_isComplete = true; // to avoid calling completed() in finishedParsing()
486     m_didCallImplicitClose = true; // don't want that one either
487
488     if (m_frame.document() && m_frame.document()->parsing()) {
489         finishedParsing();
490         m_frame.document()->setParsing(false);
491     }
492
493     if (auto* document = m_frame.document()) {
494         // FIXME: HTML5 doesn't tell us to set the state to complete when aborting, but we do anyway to match legacy behavior.
495         // http://www.w3.org/Bugs/Public/show_bug.cgi?id=10537
496         document->setReadyState(Document::Complete);
497
498         // FIXME: Should the DatabaseManager watch for something like ActiveDOMObject::stop() rather than being special-cased here?
499         DatabaseManager::singleton().stopDatabases(*document, nullptr);
500     }
501
502     policyChecker().stopCheck();
503
504     // FIXME: This will cancel redirection timer, which really needs to be restarted when restoring the frame from b/f cache.
505     m_frame.navigationScheduler().cancel();
506 }
507
508 void FrameLoader::stop()
509 {
510     // http://bugs.webkit.org/show_bug.cgi?id=10854
511     // The frame's last ref may be removed and it will be deleted by checkCompleted().
512     Ref<Frame> protect(m_frame);
513
514     if (DocumentParser* parser = m_frame.document()->parser()) {
515         parser->stopParsing();
516         parser->finish();
517     }
518 }
519
520 void FrameLoader::willTransitionToCommitted()
521 {
522     // This function is called when a frame is still fully in place (not cached, not detached), but will be replaced.
523
524     if (m_frame.editor().hasComposition()) {
525         // The text was already present in DOM, so it's better to confirm than to cancel the composition.
526         m_frame.editor().confirmComposition();
527         if (EditorClient* editorClient = m_frame.editor().client()) {
528             editorClient->respondToChangedSelection(&m_frame);
529             editorClient->discardedComposition(&m_frame);
530         }
531     }
532 }
533
534 bool FrameLoader::closeURL()
535 {
536     history().saveDocumentState();
537
538     Document* currentDocument = m_frame.document();
539     UnloadEventPolicy unloadEventPolicy;
540     if (m_frame.page() && m_frame.page()->chrome().client().isSVGImageChromeClient()) {
541         // If this is the SVGDocument of an SVGImage, no need to dispatch events or recalcStyle.
542         unloadEventPolicy = UnloadEventPolicyNone;
543     } else {
544         // Should only send the pagehide event here if the current document exists and has not been placed in the page cache.
545         unloadEventPolicy = currentDocument && currentDocument->pageCacheState() == Document::NotInPageCache ? UnloadEventPolicyUnloadAndPageHide : UnloadEventPolicyUnloadOnly;
546     }
547
548     stopLoading(unloadEventPolicy);
549     
550     m_frame.editor().clearUndoRedoOperations();
551     return true;
552 }
553
554 bool FrameLoader::didOpenURL()
555 {
556     if (m_frame.navigationScheduler().redirectScheduledDuringLoad()) {
557         // A redirect was scheduled before the document was created.
558         // This can happen when one frame changes another frame's location.
559         return false;
560     }
561
562     m_frame.navigationScheduler().cancel();
563     m_frame.editor().clearLastEditCommand();
564
565     m_isComplete = false;
566     m_didCallImplicitClose = false;
567
568     // If we are still in the process of initializing an empty document then
569     // its frame is not in a consistent state for rendering, so avoid setJSStatusBarText
570     // since it may cause clients to attempt to render the frame.
571     if (!m_stateMachine.creatingInitialEmptyDocument()) {
572         DOMWindow* window = m_frame.document()->domWindow();
573         window->setStatus(String());
574         window->setDefaultStatus(String());
575     }
576
577     started();
578
579     return true;
580 }
581
582 void FrameLoader::didExplicitOpen()
583 {
584     m_isComplete = false;
585     m_didCallImplicitClose = false;
586
587     // Calling document.open counts as committing the first real document load.
588     if (!m_stateMachine.committedFirstRealDocumentLoad())
589         m_stateMachine.advanceTo(FrameLoaderStateMachine::DisplayingInitialEmptyDocumentPostCommit);
590     
591     // Prevent window.open(url) -- eg window.open("about:blank") -- from blowing away results
592     // from a subsequent window.document.open / window.document.write call. 
593     // Canceling redirection here works for all cases because document.open 
594     // implicitly precedes document.write.
595     m_frame.navigationScheduler().cancel();
596 }
597
598
599 void FrameLoader::cancelAndClear()
600 {
601     m_frame.navigationScheduler().cancel();
602
603     if (!m_isComplete)
604         closeURL();
605
606     clear(m_frame.document(), false);
607     m_frame.script().updatePlatformScriptObjects();
608 }
609
610 static inline bool shouldClearWindowName(const Frame& frame, const Document& newDocument)
611 {
612     if (!frame.isMainFrame())
613         return false;
614
615     if (frame.loader().opener())
616         return false;
617
618     return !newDocument.securityOrigin().isSameOriginAs(frame.document()->securityOrigin());
619 }
620
621 void FrameLoader::clear(Document* newDocument, bool clearWindowProperties, bool clearScriptObjects, bool clearFrameView)
622 {
623     m_frame.editor().clear();
624
625     if (!m_needsClear)
626         return;
627     m_needsClear = false;
628     
629     if (m_frame.document()->pageCacheState() != Document::InPageCache) {
630         m_frame.document()->cancelParsing();
631         m_frame.document()->stopActiveDOMObjects();
632         bool hadLivingRenderTree = m_frame.document()->hasLivingRenderTree();
633         m_frame.document()->prepareForDestruction();
634         if (hadLivingRenderTree)
635             m_frame.document()->adjustFocusedNodeOnNodeRemoval(*m_frame.document());
636     }
637
638     // Do this after detaching the document so that the unload event works.
639     if (clearWindowProperties) {
640         InspectorInstrumentation::frameWindowDiscarded(m_frame, m_frame.document()->domWindow());
641         m_frame.document()->domWindow()->resetUnlessSuspendedForDocumentSuspension();
642         m_frame.windowProxy().clearJSWindowProxiesNotMatchingDOMWindow(newDocument->domWindow(), m_frame.document()->pageCacheState() == Document::AboutToEnterPageCache);
643
644         if (shouldClearWindowName(m_frame, *newDocument))
645             m_frame.tree().setName(nullAtom());
646     }
647
648     m_frame.selection().prepareForDestruction();
649     m_frame.eventHandler().clear();
650
651     if (clearFrameView && m_frame.view())
652         m_frame.view()->clear();
653
654     // Do not drop the document before the ScriptController and view are cleared
655     // as some destructors might still try to access the document.
656     m_frame.setDocument(nullptr);
657
658     subframeLoader().clear();
659
660     if (clearWindowProperties)
661         m_frame.windowProxy().setDOMWindow(newDocument->domWindow());
662
663     if (clearScriptObjects)
664         m_frame.script().clearScriptObjects();
665
666     m_frame.script().enableEval();
667
668     m_frame.navigationScheduler().clear();
669
670     m_checkTimer.stop();
671     m_shouldCallCheckCompleted = false;
672     m_shouldCallCheckLoadComplete = false;
673
674     if (m_stateMachine.isDisplayingInitialEmptyDocument() && m_stateMachine.committedFirstRealDocumentLoad())
675         m_stateMachine.advanceTo(FrameLoaderStateMachine::CommittedFirstRealLoad);
676 }
677
678 void FrameLoader::receivedFirstData()
679 {
680     dispatchDidCommitLoad(std::nullopt);
681     dispatchDidClearWindowObjectsInAllWorlds();
682     dispatchGlobalObjectAvailableInAllWorlds();
683
684     if (!m_documentLoader)
685         return;
686
687     auto& documentLoader = *m_documentLoader;
688     auto& title = documentLoader.title();
689     if (!title.string.isNull())
690         m_client.dispatchDidReceiveTitle(title);
691
692     ASSERT(m_frame.document());
693     auto& document = *m_frame.document();
694
695     LinkLoader::loadLinksFromHeader(documentLoader.response().httpHeaderField(HTTPHeaderName::Link), document.url(), document, LinkLoader::MediaAttributeCheck::MediaAttributeEmpty);
696
697     double delay;
698     String urlString;
699     if (!parseHTTPRefresh(documentLoader.response().httpHeaderField(HTTPHeaderName::Refresh), delay, urlString))
700         return;
701     auto completedURL = urlString.isEmpty() ? document.url() : document.completeURL(urlString);
702     if (!protocolIsJavaScript(completedURL))
703         m_frame.navigationScheduler().scheduleRedirect(document, delay, completedURL);
704     else {
705         auto message = "Refused to refresh " + document.url().stringCenterEllipsizedToLength() + " to a javascript: URL";
706         document.addConsoleMessage(MessageSource::Security, MessageLevel::Error, message);
707     }
708 }
709
710 void FrameLoader::setOutgoingReferrer(const URL& url)
711 {
712     m_outgoingReferrer = url.strippedForUseAsReferrer();
713 }
714
715 void FrameLoader::didBeginDocument(bool dispatch)
716 {
717     m_needsClear = true;
718     m_isComplete = false;
719     m_didCallImplicitClose = false;
720     m_frame.document()->setReadyState(Document::Loading);
721
722     if (m_pendingStateObject) {
723         m_frame.document()->statePopped(*m_pendingStateObject);
724         m_pendingStateObject = nullptr;
725     }
726
727     if (dispatch)
728         dispatchDidClearWindowObjectsInAllWorlds();
729
730     updateFirstPartyForCookies();
731     m_frame.document()->initContentSecurityPolicy();
732
733     const Settings& settings = m_frame.settings();
734     m_frame.document()->cachedResourceLoader().setImagesEnabled(settings.areImagesEnabled());
735     m_frame.document()->cachedResourceLoader().setAutoLoadImages(settings.loadsImagesAutomatically());
736
737     if (m_documentLoader) {
738         String dnsPrefetchControl = m_documentLoader->response().httpHeaderField(HTTPHeaderName::XDNSPrefetchControl);
739         if (!dnsPrefetchControl.isEmpty())
740             m_frame.document()->parseDNSPrefetchControlHeader(dnsPrefetchControl);
741
742         m_frame.document()->contentSecurityPolicy()->didReceiveHeaders(ContentSecurityPolicyResponseHeaders(m_documentLoader->response()), referrer(), ContentSecurityPolicy::ReportParsingErrors::No);
743
744         String referrerPolicy = m_documentLoader->response().httpHeaderField(HTTPHeaderName::ReferrerPolicy);
745         if (!referrerPolicy.isNull())
746             m_frame.document()->processReferrerPolicy(referrerPolicy, ReferrerPolicySource::HTTPHeader);
747
748         String headerContentLanguage = m_documentLoader->response().httpHeaderField(HTTPHeaderName::ContentLanguage);
749         if (!headerContentLanguage.isEmpty()) {
750             size_t commaIndex = headerContentLanguage.find(',');
751             headerContentLanguage.truncate(commaIndex); // notFound == -1 == don't truncate
752             headerContentLanguage = stripLeadingAndTrailingHTMLSpaces(headerContentLanguage);
753             if (!headerContentLanguage.isEmpty())
754                 m_frame.document()->setContentLanguage(headerContentLanguage);
755         }
756     }
757
758     history().restoreDocumentState();
759 }
760
761 void FrameLoader::finishedParsing()
762 {
763     LOG(Loading, "WebCoreLoading %s: Finished parsing", m_frame.tree().uniqueName().string().utf8().data());
764
765     m_frame.injectUserScripts(InjectAtDocumentEnd);
766
767     if (m_stateMachine.creatingInitialEmptyDocument())
768         return;
769
770     // This can be called from the Frame's destructor, in which case we shouldn't protect ourselves
771     // because doing so will cause us to re-enter the destructor when protector goes out of scope.
772     // Null-checking the FrameView indicates whether or not we're in the destructor.
773     RefPtr<Frame> protector = m_frame.view() ? &m_frame : 0;
774
775     m_client.dispatchDidFinishDocumentLoad();
776
777     scrollToFragmentWithParentBoundary(m_frame.document()->url());
778
779     checkCompleted();
780
781     if (!m_frame.view())
782         return; // We are being destroyed by something checkCompleted called.
783
784     // Check if the scrollbars are really needed for the content.
785     // If not, remove them, relayout, and repaint.
786     m_frame.view()->restoreScrollbar();
787 }
788
789 void FrameLoader::loadDone(LoadCompletionType type)
790 {
791     if (type == LoadCompletionType::Finish)
792         checkCompleted();
793     else
794         scheduleCheckCompleted();
795 }
796
797 void FrameLoader::subresourceLoadDone(LoadCompletionType type)
798 {
799     if (type == LoadCompletionType::Finish)
800         checkLoadComplete();
801     else
802         scheduleCheckLoadComplete();
803 }
804
805 bool FrameLoader::allChildrenAreComplete() const
806 {
807     for (Frame* child = m_frame.tree().firstChild(); child; child = child->tree().nextSibling()) {
808         if (!child->loader().m_isComplete)
809             return false;
810     }
811     return true;
812 }
813
814 bool FrameLoader::allAncestorsAreComplete() const
815 {
816     for (Frame* ancestor = &m_frame; ancestor; ancestor = ancestor->tree().parent()) {
817         if (!ancestor->loader().m_isComplete)
818             return false;
819     }
820     return true;
821 }
822
823 void FrameLoader::checkCompleted()
824 {
825     RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(ScriptDisallowedScope::InMainThread::isScriptAllowed());
826     m_shouldCallCheckCompleted = false;
827
828     // Have we completed before?
829     if (m_isComplete)
830         return;
831     
832 #if ENABLE(VIDEO)
833     // FIXME: Remove this code once https://webkit.org/b/185284 is fixed.
834     if (HTMLMediaElement::isRunningDestructor()) {
835         ASSERT_NOT_REACHED();
836         scheduleCheckCompleted();
837         return;
838     }
839 #endif
840
841     // FIXME: It would be better if resource loads were kicked off after render tree update (or didn't complete synchronously).
842     //        https://bugs.webkit.org/show_bug.cgi?id=171729
843     if (m_frame.document()->inRenderTreeUpdate()) {
844         scheduleCheckCompleted();
845         return;
846     }
847
848     // Are we still parsing?
849     if (m_frame.document()->parsing())
850         return;
851
852     // Still waiting for images/scripts?
853     if (m_frame.document()->cachedResourceLoader().requestCount())
854         return;
855
856     // Still waiting for elements that don't go through a FrameLoader?
857     if (m_frame.document()->isDelayingLoadEvent())
858         return;
859
860     auto* scriptableParser = m_frame.document()->scriptableDocumentParser();
861     if (scriptableParser && scriptableParser->hasScriptsWaitingForStylesheets())
862         return;
863
864     // Any frame that hasn't completed yet?
865     if (!allChildrenAreComplete())
866         return;
867
868     // Important not to protect earlier in this function, because earlier parts
869     // of this function can be called in the frame's destructor, and it's not legal
870     // to ref an object while it's being destroyed.
871     Ref<Frame> protect(m_frame);
872
873     // OK, completed.
874     m_isComplete = true;
875     m_requestedHistoryItem = nullptr;
876     m_frame.document()->setReadyState(Document::Complete);
877
878 #if PLATFORM(IOS)
879     if (m_frame.document()->url().isEmpty()) {
880         // We need to update the document URL of a PDF document to be non-empty so that both back/forward history navigation
881         // between PDF pages and fragment navigation works. See <rdar://problem/9544769> for more details.
882         // FIXME: Is there a better place for this code, say DocumentLoader? Also, we should explicitly only update the URL
883         // of the document when it's a PDFDocument object instead of assuming that a Document object with an empty URL is a PDFDocument.
884         // FIXME: This code is incorrect for a synthesized document (which also has an empty URL). The URL for a synthesized
885         // document should be the URL specified to FrameLoader::initForSynthesizedDocument().
886         m_frame.document()->setURL(activeDocumentLoader()->documentURL());
887     }
888 #endif
889
890     checkCallImplicitClose(); // if we didn't do it before
891
892     m_frame.navigationScheduler().startTimer();
893
894     completed();
895     if (m_frame.page())
896         checkLoadComplete();
897 }
898
899 void FrameLoader::checkTimerFired()
900 {
901     checkCompletenessNow();
902 }
903
904 void FrameLoader::checkCompletenessNow()
905 {
906     Ref<Frame> protect(m_frame);
907
908     if (Page* page = m_frame.page()) {
909         if (page->defersLoading())
910             return;
911     }
912     if (m_shouldCallCheckCompleted)
913         checkCompleted();
914     if (m_shouldCallCheckLoadComplete)
915         checkLoadComplete();
916 }
917
918 void FrameLoader::startCheckCompleteTimer()
919 {
920     if (!(m_shouldCallCheckCompleted || m_shouldCallCheckLoadComplete))
921         return;
922     if (m_checkTimer.isActive())
923         return;
924     m_checkTimer.startOneShot(0_s);
925 }
926
927 void FrameLoader::scheduleCheckCompleted()
928 {
929     m_shouldCallCheckCompleted = true;
930     startCheckCompleteTimer();
931 }
932
933 void FrameLoader::scheduleCheckLoadComplete()
934 {
935     m_shouldCallCheckLoadComplete = true;
936     startCheckCompleteTimer();
937 }
938
939 void FrameLoader::checkCallImplicitClose()
940 {
941     if (m_didCallImplicitClose || m_frame.document()->parsing() || m_frame.document()->isDelayingLoadEvent())
942         return;
943
944     if (!allChildrenAreComplete())
945         return; // still got a frame running -> too early
946
947     m_didCallImplicitClose = true;
948     m_wasUnloadEventEmitted = false;
949     m_frame.document()->implicitClose();
950 }
951
952 void FrameLoader::loadURLIntoChildFrame(const URL& url, const String& referer, Frame* childFrame)
953 {
954     ASSERT(childFrame);
955
956 #if ENABLE(WEB_ARCHIVE) || ENABLE(MHTML)
957     if (auto activeLoader = activeDocumentLoader()) {
958         if (auto subframeArchive = activeLoader->popArchiveForSubframe(childFrame->tree().uniqueName(), url)) {
959             childFrame->loader().loadArchive(RefPtr<Archive> { subframeArchive }.releaseNonNull());
960             return;
961         }
962     }
963 #endif
964
965     // If we're moving in the back/forward list, we might want to replace the content
966     // of this child frame with whatever was there at that point.
967     auto* parentItem = history().currentItem();
968     if (parentItem && parentItem->children().size() && isBackForwardLoadType(loadType()) && !m_frame.document()->loadEventFinished()) {
969         if (auto* childItem = parentItem->childItemWithTarget(childFrame->tree().uniqueName())) {
970             childFrame->loader().m_requestedHistoryItem = childItem;
971             childFrame->loader().loadDifferentDocumentItem(*childItem, loadType(), MayAttemptCacheOnlyLoadForFormSubmissionItem, ShouldTreatAsContinuingLoad::No);
972             return;
973         }
974     }
975
976     auto* lexicalFrame = lexicalFrameFromCommonVM();
977     auto initiatedByMainFrame = lexicalFrame && lexicalFrame->isMainFrame() ? InitiatedByMainFrame::Yes : InitiatedByMainFrame::Unknown;
978
979     FrameLoadRequest frameLoadRequest { *m_frame.document(), m_frame.document()->securityOrigin(), { url }, "_self"_s, LockHistory::No, LockBackForwardList::Yes, ShouldSendReferrer::MaybeSendReferrer, AllowNavigationToInvalidURL::Yes, NewFrameOpenerPolicy::Suppress, ShouldOpenExternalURLsPolicy::ShouldNotAllow, initiatedByMainFrame };
980     childFrame->loader().loadURL(WTFMove(frameLoadRequest), referer, FrameLoadType::RedirectWithLockedBackForwardList, nullptr, { }, [] { });
981 }
982
983 #if ENABLE(WEB_ARCHIVE) || ENABLE(MHTML)
984
985 void FrameLoader::loadArchive(Ref<Archive>&& archive)
986 {
987     ArchiveResource* mainResource = archive->mainResource();
988     ASSERT(mainResource);
989     if (!mainResource)
990         return;
991
992     ResourceResponse response(URL(), mainResource->mimeType(), mainResource->data().size(), mainResource->textEncoding());
993     SubstituteData substituteData(&mainResource->data(), URL(), response, SubstituteData::SessionHistoryVisibility::Hidden);
994     
995     ResourceRequest request(mainResource->url());
996
997     auto documentLoader = m_client.createDocumentLoader(request, substituteData);
998     documentLoader->setArchive(WTFMove(archive));
999     load(documentLoader.get(), ShouldSkipSafeBrowsingCheck::No);
1000 }
1001
1002 #endif // ENABLE(WEB_ARCHIVE) || ENABLE(MHTML)
1003
1004 String FrameLoader::outgoingReferrer() const
1005 {
1006     // See http://www.whatwg.org/specs/web-apps/current-work/#fetching-resources
1007     // for why we walk the parent chain for srcdoc documents.
1008     Frame* frame = &m_frame;
1009     while (frame && frame->document()->isSrcdocDocument()) {
1010         frame = frame->tree().parent();
1011         // Srcdoc documents cannot be top-level documents, by definition,
1012         // because they need to be contained in iframes with the srcdoc.
1013         ASSERT(frame);
1014     }
1015     if (!frame)
1016         return emptyString();
1017     return frame->loader().m_outgoingReferrer;
1018 }
1019
1020 String FrameLoader::outgoingOrigin() const
1021 {
1022     return m_frame.document()->securityOrigin().toString();
1023 }
1024
1025 bool FrameLoader::checkIfFormActionAllowedByCSP(const URL& url, bool didReceiveRedirectResponse) const
1026 {
1027     if (m_submittedFormURL.isEmpty())
1028         return true;
1029
1030     auto redirectResponseReceived = didReceiveRedirectResponse ? ContentSecurityPolicy::RedirectResponseReceived::Yes : ContentSecurityPolicy::RedirectResponseReceived::No;
1031     return m_frame.document()->contentSecurityPolicy()->allowFormAction(url, redirectResponseReceived);
1032 }
1033
1034 Frame* FrameLoader::opener()
1035 {
1036     return m_opener;
1037 }
1038
1039 void FrameLoader::setOpener(Frame* opener)
1040 {
1041     if (m_opener && !opener)
1042         m_client.didDisownOpener();
1043
1044     if (m_opener) {
1045         // When setOpener is called in ~FrameLoader, opener's m_frameLoader is already cleared.
1046         auto& openerFrameLoader = m_opener == &m_frame ? *this : m_opener->loader();
1047         openerFrameLoader.m_openedFrames.remove(&m_frame);
1048     }
1049     if (opener)
1050         opener->loader().m_openedFrames.add(&m_frame);
1051     m_opener = opener;
1052
1053     if (m_frame.document())
1054         m_frame.document()->initSecurityContext();
1055 }
1056
1057 // FIXME: This does not belong in FrameLoader!
1058 void FrameLoader::handleFallbackContent()
1059 {
1060     HTMLFrameOwnerElement* owner = m_frame.ownerElement();
1061     if (!is<HTMLObjectElement>(owner))
1062         return;
1063     downcast<HTMLObjectElement>(*owner).renderFallbackContent();
1064 }
1065
1066 void FrameLoader::provisionalLoadStarted()
1067 {
1068     if (m_stateMachine.firstLayoutDone())
1069         m_stateMachine.advanceTo(FrameLoaderStateMachine::CommittedFirstRealLoad);
1070     m_frame.navigationScheduler().cancel(true);
1071     m_client.provisionalLoadStarted();
1072
1073     if (m_frame.isMainFrame()) {
1074         tracePoint(MainResourceLoadDidStartProvisional);
1075
1076         if (auto* page = m_frame.page())
1077             page->didStartProvisionalLoad();
1078     }
1079 }
1080
1081 void FrameLoader::resetMultipleFormSubmissionProtection()
1082 {
1083     m_submittedFormURL = URL();
1084 }
1085
1086 void FrameLoader::updateFirstPartyForCookies()
1087 {
1088     if (m_frame.tree().parent())
1089         setFirstPartyForCookies(m_frame.tree().parent()->document()->firstPartyForCookies());
1090     else
1091         setFirstPartyForCookies(m_frame.document()->url());
1092 }
1093
1094 void FrameLoader::setFirstPartyForCookies(const URL& url)
1095 {
1096     for (Frame* frame = &m_frame; frame; frame = frame->tree().traverseNext(&m_frame))
1097         frame->document()->setFirstPartyForCookies(url);
1098
1099     String registrableDomain = ResourceRequest::partitionName(url.host().toString());
1100     for (Frame* frame = &m_frame; frame; frame = frame->tree().traverseNext(&m_frame)) {
1101         if (SecurityPolicy::shouldInheritSecurityOriginFromOwner(frame->document()->url()) || registrableDomainsAreEqual(frame->document()->url(), registrableDomain))
1102             frame->document()->setSiteForCookies(url);
1103     }
1104 }
1105
1106 // This does the same kind of work that didOpenURL does, except it relies on the fact
1107 // that a higher level already checked that the URLs match and the scrolling is the right thing to do.
1108 void FrameLoader::loadInSameDocument(const URL& url, SerializedScriptValue* stateObject, bool isNewNavigation)
1109 {
1110     // If we have a state object, we cannot also be a new navigation.
1111     ASSERT(!stateObject || (stateObject && !isNewNavigation));
1112
1113     // Update the data source's request with the new URL to fake the URL change
1114     URL oldURL = m_frame.document()->url();
1115     m_frame.document()->setURL(url);
1116     setOutgoingReferrer(url);
1117     documentLoader()->replaceRequestURLForSameDocumentNavigation(url);
1118     if (isNewNavigation && !shouldTreatURLAsSameAsCurrent(url) && !stateObject) {
1119         // NB: must happen after replaceRequestURLForSameDocumentNavigation(), since we add 
1120         // based on the current request. Must also happen before we openURL and displace the 
1121         // scroll position, since adding the BF item will save away scroll state.
1122         
1123         // NB2: If we were loading a long, slow doc, and the user fragment navigated before
1124         // it was done, currItem is now set the that slow doc, and prevItem is whatever was
1125         // before it.  Adding the b/f item will bump the slow doc down to prevItem, even
1126         // though its load is not yet done.  I think this all works out OK, for one because
1127         // we have already saved away the scroll and doc state for the long slow load,
1128         // but it's not an obvious case.
1129
1130         history().updateBackForwardListForFragmentScroll();
1131     }
1132     
1133     bool hashChange = equalIgnoringFragmentIdentifier(url, oldURL) && url.fragmentIdentifier() != oldURL.fragmentIdentifier();
1134     
1135     history().updateForSameDocumentNavigation();
1136
1137     // If we were in the autoscroll/panScroll mode we want to stop it before following the link to the anchor
1138     if (hashChange)
1139         m_frame.eventHandler().stopAutoscrollTimer();
1140     
1141     // It's important to model this as a load that starts and immediately finishes.
1142     // Otherwise, the parent frame may think we never finished loading.
1143     started();
1144
1145     if (auto* ownerElement = m_frame.ownerElement()) {
1146         auto* ownerRenderer = ownerElement->renderer();
1147         auto* view = m_frame.view();
1148         if (is<RenderWidget>(ownerRenderer) && view)
1149             downcast<RenderWidget>(*ownerRenderer).setWidget(view);
1150     }
1151
1152     // We need to scroll to the fragment whether or not a hash change occurred, since
1153     // the user might have scrolled since the previous navigation.
1154     scrollToFragmentWithParentBoundary(url, isNewNavigation);
1155     
1156     m_isComplete = false;
1157     checkCompleted();
1158
1159     if (isNewNavigation) {
1160         // This will clear previousItem from the rest of the frame tree that didn't
1161         // doing any loading. We need to make a pass on this now, since for fragment
1162         // navigation we'll not go through a real load and reach Completed state.
1163         checkLoadComplete();
1164     }
1165
1166     m_client.dispatchDidNavigateWithinPage();
1167
1168     m_frame.document()->statePopped(stateObject ? Ref<SerializedScriptValue> { *stateObject } : SerializedScriptValue::nullValue());
1169     m_client.dispatchDidPopStateWithinPage();
1170     
1171     if (hashChange) {
1172         m_frame.document()->enqueueHashchangeEvent(oldURL, url);
1173         m_client.dispatchDidChangeLocationWithinPage();
1174     }
1175     
1176     // FrameLoaderClient::didFinishLoad() tells the internal load delegate the load finished with no error
1177     m_client.didFinishLoad();
1178 }
1179
1180 bool FrameLoader::isComplete() const
1181 {
1182     return m_isComplete;
1183 }
1184
1185 void FrameLoader::completed()
1186 {
1187     Ref<Frame> protect(m_frame);
1188
1189     for (Frame* descendant = m_frame.tree().traverseNext(&m_frame); descendant; descendant = descendant->tree().traverseNext(&m_frame))
1190         descendant->navigationScheduler().startTimer();
1191
1192     if (Frame* parent = m_frame.tree().parent())
1193         parent->loader().checkCompleted();
1194
1195     if (m_frame.view())
1196         m_frame.view()->maintainScrollPositionAtAnchor(nullptr);
1197 }
1198
1199 void FrameLoader::started()
1200 {
1201     for (Frame* frame = &m_frame; frame; frame = frame->tree().parent())
1202         frame->loader().m_isComplete = false;
1203 }
1204
1205 void FrameLoader::prepareForLoadStart()
1206 {
1207     RELEASE_LOG_IF_ALLOWED("prepareForLoadStart: Starting frame load (frame = %p, main = %d)", &m_frame, m_frame.isMainFrame());
1208
1209     m_progressTracker->progressStarted();
1210     m_client.dispatchDidStartProvisionalLoad();
1211
1212     if (AXObjectCache::accessibilityEnabled()) {
1213         if (AXObjectCache* cache = m_frame.document()->existingAXObjectCache()) {
1214             AXObjectCache::AXLoadingEvent loadingEvent = loadType() == FrameLoadType::Reload ? AXObjectCache::AXLoadingReloaded : AXObjectCache::AXLoadingStarted;
1215             cache->frameLoadingEventNotification(&m_frame, loadingEvent);
1216         }
1217     }
1218 }
1219
1220 void FrameLoader::setupForReplace()
1221 {
1222     m_client.revertToProvisionalState(m_documentLoader.get());
1223     setState(FrameStateProvisional);
1224     m_provisionalDocumentLoader = m_documentLoader;
1225     m_documentLoader = nullptr;
1226     detachChildren();
1227 }
1228
1229 void FrameLoader::loadFrameRequest(FrameLoadRequest&& request, Event* event, RefPtr<FormState>&& formState)
1230 {
1231     // Protect frame from getting blown away inside dispatchBeforeLoadEvent in loadWithDocumentLoader.
1232     auto protectFrame = makeRef(m_frame);
1233
1234     URL url = request.resourceRequest().url();
1235
1236     ASSERT(m_frame.document());
1237     if (!request.requesterSecurityOrigin().canDisplay(url)) {
1238         reportLocalLoadFailed(&m_frame, url.stringCenterEllipsizedToLength());
1239         return;
1240     }
1241
1242     String argsReferrer = request.resourceRequest().httpReferrer();
1243     if (argsReferrer.isEmpty())
1244         argsReferrer = outgoingReferrer();
1245
1246     String referrer = SecurityPolicy::generateReferrerHeader(m_frame.document()->referrerPolicy(), url, argsReferrer);
1247     if (request.shouldSendReferrer() == NeverSendReferrer)
1248         referrer = String();
1249
1250     FrameLoadType loadType;
1251     if (request.resourceRequest().cachePolicy() == ResourceRequestCachePolicy::ReloadIgnoringCacheData)
1252         loadType = FrameLoadType::Reload;
1253     else if (request.lockBackForwardList() == LockBackForwardList::Yes)
1254         loadType = FrameLoadType::RedirectWithLockedBackForwardList;
1255     else
1256         loadType = FrameLoadType::Standard;
1257
1258     auto completionHandler = [this, protectedFrame = makeRef(m_frame), formState = makeWeakPtr(formState.get()), frameName = request.frameName()] {
1259         // FIXME: It's possible this targetFrame will not be the same frame that was targeted by the actual
1260         // load if frame names have changed.
1261         Frame* sourceFrame = formState ? formState->sourceDocument().frame() : &m_frame;
1262         if (!sourceFrame)
1263             sourceFrame = &m_frame;
1264         Frame* targetFrame = sourceFrame->loader().findFrameForNavigation(frameName);
1265         if (targetFrame && targetFrame != sourceFrame) {
1266             if (Page* page = targetFrame->page())
1267                 page->chrome().focus();
1268         }
1269     };
1270
1271     if (request.resourceRequest().httpMethod() == "POST")
1272         loadPostRequest(WTFMove(request), referrer, loadType, event, WTFMove(formState), WTFMove(completionHandler));
1273     else
1274         loadURL(WTFMove(request), referrer, loadType, event, WTFMove(formState), WTFMove(completionHandler));
1275 }
1276
1277 static ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicyToApply(Frame& currentFrame, InitiatedByMainFrame initiatedByMainFrame, ShouldOpenExternalURLsPolicy propagatedPolicy)
1278 {
1279     if (UserGestureIndicator::processingUserGesture())
1280         return ShouldOpenExternalURLsPolicy::ShouldAllow;
1281
1282     if (initiatedByMainFrame == InitiatedByMainFrame::Yes)
1283         return propagatedPolicy;
1284
1285     if (!currentFrame.isMainFrame())
1286         return ShouldOpenExternalURLsPolicy::ShouldNotAllow;
1287
1288     return propagatedPolicy;
1289 }
1290
1291 static ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicyToApply(Frame& currentFrame, const FrameLoadRequest& frameLoadRequest)
1292 {
1293     return shouldOpenExternalURLsPolicyToApply(currentFrame, frameLoadRequest.initiatedByMainFrame(), frameLoadRequest.shouldOpenExternalURLsPolicy());
1294 }
1295
1296 static void applyShouldOpenExternalURLsPolicyToNewDocumentLoader(Frame& frame, DocumentLoader& documentLoader, InitiatedByMainFrame initiatedByMainFrame, ShouldOpenExternalURLsPolicy propagatedPolicy)
1297 {
1298     documentLoader.setShouldOpenExternalURLsPolicy(shouldOpenExternalURLsPolicyToApply(frame, initiatedByMainFrame, propagatedPolicy));
1299 }
1300
1301 static void applyShouldOpenExternalURLsPolicyToNewDocumentLoader(Frame& frame, DocumentLoader& documentLoader, const FrameLoadRequest& frameLoadRequest)
1302 {
1303     documentLoader.setShouldOpenExternalURLsPolicy(shouldOpenExternalURLsPolicyToApply(frame, frameLoadRequest));
1304 }
1305
1306 bool FrameLoader::isNavigationAllowed() const
1307 {
1308     return m_pageDismissalEventBeingDispatched == PageDismissalType::None && NavigationDisabler::isNavigationAllowed(m_frame);
1309 }
1310
1311 bool FrameLoader::isStopLoadingAllowed() const
1312 {
1313     return m_pageDismissalEventBeingDispatched == PageDismissalType::None;
1314 }
1315
1316 void FrameLoader::loadURL(FrameLoadRequest&& frameLoadRequest, const String& referrer, FrameLoadType newLoadType, Event* event, RefPtr<FormState>&& formState, CompletionHandler<void()>&& completionHandler)
1317 {
1318     CompletionHandlerCallingScope completionHandlerCaller(WTFMove(completionHandler));
1319     if (m_inStopAllLoaders || m_inClearProvisionalLoadForPolicyCheck)
1320         return;
1321
1322     Ref<Frame> protect(m_frame);
1323
1324     String frameName = frameLoadRequest.frameName();
1325     AllowNavigationToInvalidURL allowNavigationToInvalidURL = frameLoadRequest.allowNavigationToInvalidURL();
1326     NewFrameOpenerPolicy openerPolicy = frameLoadRequest.newFrameOpenerPolicy();
1327     LockHistory lockHistory = frameLoadRequest.lockHistory();
1328     bool isFormSubmission = formState;
1329
1330     const URL& newURL = frameLoadRequest.resourceRequest().url();
1331     ResourceRequest request(newURL);
1332     if (!referrer.isEmpty()) {
1333         request.setHTTPReferrer(referrer);
1334         RefPtr<SecurityOrigin> referrerOrigin = SecurityOrigin::createFromString(referrer);
1335         addHTTPOriginIfNeeded(request, referrerOrigin->toString());
1336     }
1337     if (&m_frame.tree().top() != &m_frame)
1338         request.setDomainForCachePartition(m_frame.tree().top().document()->domainForCachePartition());
1339
1340     addExtraFieldsToRequest(request, newLoadType, true);
1341     if (isReload(newLoadType))
1342         request.setCachePolicy(ResourceRequestCachePolicy::ReloadIgnoringCacheData);
1343
1344     ASSERT(newLoadType != FrameLoadType::Same);
1345
1346     // The search for a target frame is done earlier in the case of form submission.
1347     Frame* targetFrame = isFormSubmission ? nullptr : findFrameForNavigation(frameName);
1348     if (targetFrame && targetFrame != &m_frame) {
1349         frameLoadRequest.setFrameName("_self");
1350         targetFrame->loader().loadURL(WTFMove(frameLoadRequest), referrer, newLoadType, event, WTFMove(formState), completionHandlerCaller.release());
1351         return;
1352     }
1353
1354     if (!isNavigationAllowed())
1355         return;
1356
1357     NavigationAction action { frameLoadRequest.requester(), request, frameLoadRequest.initiatedByMainFrame(), newLoadType, isFormSubmission, event, frameLoadRequest.shouldOpenExternalURLsPolicy(), frameLoadRequest.downloadAttribute() };
1358     if (m_frame.page() && m_frame.page()->openedViaWindowOpenWithOpener())
1359         action.setOpenedViaWindowOpenWithOpener();
1360     action.setHasOpenedFrames(!m_openedFrames.isEmpty());
1361
1362     if (!targetFrame && !frameName.isEmpty()) {
1363         action = action.copyWithShouldOpenExternalURLsPolicy(shouldOpenExternalURLsPolicyToApply(m_frame, frameLoadRequest));
1364         policyChecker().checkNewWindowPolicy(WTFMove(action), WTFMove(request), WTFMove(formState), frameName, [this, allowNavigationToInvalidURL, openerPolicy, completionHandler = completionHandlerCaller.release()] (const ResourceRequest& request, WeakPtr<FormState>&& formState, const String& frameName, const NavigationAction& action, ShouldContinue shouldContinue) mutable {
1365             continueLoadAfterNewWindowPolicy(request, formState.get(), frameName, action, shouldContinue, allowNavigationToInvalidURL, openerPolicy);
1366             completionHandler();
1367         });
1368         return;
1369     }
1370
1371     RefPtr<DocumentLoader> oldDocumentLoader = m_documentLoader;
1372
1373     bool sameURL = shouldTreatURLAsSameAsCurrent(newURL);
1374     const String& httpMethod = request.httpMethod();
1375     
1376     // Make sure to do scroll to fragment processing even if the URL is
1377     // exactly the same so pages with '#' links and DHTML side effects
1378     // work properly.
1379     if (shouldPerformFragmentNavigation(isFormSubmission, httpMethod, newLoadType, newURL)) {
1380         oldDocumentLoader->setTriggeringAction(WTFMove(action));
1381         oldDocumentLoader->setLastCheckedRequest(ResourceRequest());
1382         policyChecker().stopCheck();
1383         policyChecker().setLoadType(newLoadType);
1384         policyChecker().checkNavigationPolicy(WTFMove(request), ResourceResponse { } /* redirectResponse */, oldDocumentLoader.get(), WTFMove(formState), [this, protectedFrame = makeRef(m_frame)] (const ResourceRequest& request, WeakPtr<FormState>&&, ShouldContinue shouldContinue) {
1385             continueFragmentScrollAfterNavigationPolicy(request, shouldContinue == ShouldContinue::Yes);
1386         }, PolicyDecisionMode::Synchronous);
1387         return;
1388     }
1389
1390     // Must grab this now, since this load may stop the previous load and clear this flag.
1391     bool isRedirect = m_quickRedirectComing;
1392 #if USE(SYSTEM_PREVIEW)
1393     bool isSystemPreview = frameLoadRequest.isSystemPreview();
1394     request.setSystemPreview(isSystemPreview);
1395     if (isSystemPreview)
1396         request.setSystemPreviewRect(frameLoadRequest.systemPreviewRect());
1397 #endif
1398     loadWithNavigationAction(request, WTFMove(action), lockHistory, newLoadType, WTFMove(formState), allowNavigationToInvalidURL, frameLoadRequest.shouldSkipSafeBrowsingCheck(), [this, isRedirect, sameURL, newLoadType, protectedFrame = makeRef(m_frame), completionHandler = completionHandlerCaller.release()] () mutable {
1399         if (isRedirect) {
1400             m_quickRedirectComing = false;
1401             if (m_provisionalDocumentLoader)
1402                 m_provisionalDocumentLoader->setIsClientRedirect(true);
1403             else if (m_policyDocumentLoader)
1404                 m_policyDocumentLoader->setIsClientRedirect(true);
1405         } else if (sameURL && !isReload(newLoadType)) {
1406             // Example of this case are sites that reload the same URL with a different cookie
1407             // driving the generated content, or a master frame with links that drive a target
1408             // frame, where the user has clicked on the same link repeatedly.
1409             m_loadType = FrameLoadType::Same;
1410         }
1411         completionHandler();
1412     });
1413 }
1414
1415 SubstituteData FrameLoader::defaultSubstituteDataForURL(const URL& url)
1416 {
1417     if (!shouldTreatURLAsSrcdocDocument(url))
1418         return SubstituteData();
1419     auto& srcdoc = m_frame.ownerElement()->attributeWithoutSynchronization(srcdocAttr);
1420     ASSERT(!srcdoc.isNull());
1421     CString encodedSrcdoc = srcdoc.string().utf8();
1422
1423     ResourceResponse response(URL(), "text/html"_s, encodedSrcdoc.length(), "UTF-8"_s);
1424     return SubstituteData(SharedBuffer::create(encodedSrcdoc.data(), encodedSrcdoc.length()), URL(), response, SubstituteData::SessionHistoryVisibility::Hidden);
1425 }
1426
1427 void FrameLoader::load(FrameLoadRequest&& request)
1428 {
1429     if (m_inStopAllLoaders || m_inClearProvisionalLoadForPolicyCheck)
1430         return;
1431
1432     if (!request.frameName().isEmpty()) {
1433         Frame* frame = findFrameForNavigation(request.frameName());
1434         if (frame) {
1435             request.setShouldCheckNewWindowPolicy(false);
1436             if (&frame->loader() != this) {
1437                 frame->loader().load(WTFMove(request));
1438                 return;
1439             }
1440         }
1441     }
1442
1443     if (request.shouldCheckNewWindowPolicy()) {
1444         NavigationAction action { request.requester(), request.resourceRequest(), InitiatedByMainFrame::Unknown, NavigationType::Other, request.shouldOpenExternalURLsPolicy() };
1445         policyChecker().checkNewWindowPolicy(WTFMove(action), WTFMove(request.resourceRequest()), { }, request.frameName(), [this] (const ResourceRequest& request, WeakPtr<FormState>&& formState, const String& frameName, const NavigationAction& action, ShouldContinue shouldContinue) {
1446             continueLoadAfterNewWindowPolicy(request, formState.get(), frameName, action, shouldContinue, AllowNavigationToInvalidURL::Yes, NewFrameOpenerPolicy::Suppress);
1447         });
1448
1449         return;
1450     }
1451
1452     if (!request.hasSubstituteData())
1453         request.setSubstituteData(defaultSubstituteDataForURL(request.resourceRequest().url()));
1454
1455     Ref<DocumentLoader> loader = m_client.createDocumentLoader(request.resourceRequest(), request.substituteData());
1456     addSameSiteInfoToRequestIfNeeded(loader->request());
1457     applyShouldOpenExternalURLsPolicyToNewDocumentLoader(m_frame, loader, request);
1458
1459     SetForScope<bool> currentLoadShouldBeTreatedAsContinuingLoadGuard(m_currentLoadShouldBeTreatedAsContinuingLoad, request.shouldTreatAsContinuingLoad());
1460     load(loader.get(), request.shouldSkipSafeBrowsingCheck());
1461 }
1462
1463 void FrameLoader::loadWithNavigationAction(const ResourceRequest& request, NavigationAction&& action, LockHistory lockHistory, FrameLoadType type, RefPtr<FormState>&& formState, AllowNavigationToInvalidURL allowNavigationToInvalidURL, ShouldSkipSafeBrowsingCheck shouldSkipSafeBrowsingCheck, CompletionHandler<void()>&& completionHandler)
1464 {
1465     Ref<DocumentLoader> loader = m_client.createDocumentLoader(request, defaultSubstituteDataForURL(request.url()));
1466     applyShouldOpenExternalURLsPolicyToNewDocumentLoader(m_frame, loader, action.initiatedByMainFrame(), action.shouldOpenExternalURLsPolicy());
1467
1468     if (lockHistory == LockHistory::Yes && m_documentLoader)
1469         loader->setClientRedirectSourceForHistory(m_documentLoader->didCreateGlobalHistoryEntry() ? m_documentLoader->urlForHistory().string() : m_documentLoader->clientRedirectSourceForHistory());
1470
1471     if (auto* opener = this->opener()) {
1472         auto pageID = opener->loader().client().pageID();
1473         auto frameID = opener->loader().client().frameID();
1474         if (pageID && frameID)
1475             action.setOpener(std::make_pair(*pageID, *frameID));
1476     }
1477
1478     loader->setTriggeringAction(WTFMove(action));
1479     if (m_documentLoader)
1480         loader->setOverrideEncoding(m_documentLoader->overrideEncoding());
1481
1482     loadWithDocumentLoader(loader.ptr(), type, WTFMove(formState), allowNavigationToInvalidURL, ShouldTreatAsContinuingLoad::No, shouldSkipSafeBrowsingCheck, WTFMove(completionHandler));
1483 }
1484
1485 void FrameLoader::load(DocumentLoader& newDocumentLoader, ShouldSkipSafeBrowsingCheck shouldSkipSafeBrowsingCheck)
1486 {
1487     ResourceRequest& r = newDocumentLoader.request();
1488     addExtraFieldsToMainResourceRequest(r);
1489     FrameLoadType type;
1490
1491     if (shouldTreatURLAsSameAsCurrent(newDocumentLoader.originalRequest().url())) {
1492         r.setCachePolicy(ResourceRequestCachePolicy::ReloadIgnoringCacheData);
1493         type = FrameLoadType::Same;
1494     } else if (shouldTreatURLAsSameAsCurrent(newDocumentLoader.unreachableURL()) && isReload(m_loadType))
1495         type = m_loadType;
1496     else if (m_loadType == FrameLoadType::RedirectWithLockedBackForwardList && !newDocumentLoader.unreachableURL().isEmpty() && newDocumentLoader.substituteData().isValid())
1497         type = FrameLoadType::RedirectWithLockedBackForwardList;
1498     else
1499         type = FrameLoadType::Standard;
1500
1501     if (m_documentLoader)
1502         newDocumentLoader.setOverrideEncoding(m_documentLoader->overrideEncoding());
1503     
1504     // When we loading alternate content for an unreachable URL that we're
1505     // visiting in the history list, we treat it as a reload so the history list 
1506     // is appropriately maintained.
1507     //
1508     // FIXME: This seems like a dangerous overloading of the meaning of "FrameLoadType::Reload" ...
1509     // shouldn't a more explicit type of reload be defined, that means roughly 
1510     // "load without affecting history" ? 
1511     if (shouldReloadToHandleUnreachableURL(newDocumentLoader)) {
1512         // shouldReloadToHandleUnreachableURL returns true only when the original load type is back-forward.
1513         // In this case we should save the document state now. Otherwise the state can be lost because load type is
1514         // changed and updateForBackForwardNavigation() will not be called when loading is committed.
1515         history().saveDocumentAndScrollState();
1516
1517         ASSERT(type == FrameLoadType::Standard);
1518         type = FrameLoadType::Reload;
1519     }
1520
1521     loadWithDocumentLoader(&newDocumentLoader, type, nullptr, AllowNavigationToInvalidURL::Yes, ShouldTreatAsContinuingLoad::No, shouldSkipSafeBrowsingCheck);
1522 }
1523
1524 void FrameLoader::loadWithDocumentLoader(DocumentLoader* loader, FrameLoadType type, RefPtr<FormState>&& formState, AllowNavigationToInvalidURL allowNavigationToInvalidURL, ShouldTreatAsContinuingLoad, ShouldSkipSafeBrowsingCheck shouldSkipSafeBrowsingCheck, CompletionHandler<void()>&& completionHandler)
1525 {
1526     // Retain because dispatchBeforeLoadEvent may release the last reference to it.
1527     Ref<Frame> protect(m_frame);
1528
1529     CompletionHandlerCallingScope completionHandlerCaller(WTFMove(completionHandler));
1530
1531     ASSERT(m_client.hasWebView());
1532
1533     // Unfortunately the view must be non-nil, this is ultimately due
1534     // to parser requiring a FrameView.  We should fix this dependency.
1535
1536     ASSERT(m_frame.view());
1537
1538     if (!isNavigationAllowed())
1539         return;
1540
1541     if (m_frame.document())
1542         m_previousURL = m_frame.document()->url();
1543
1544     const URL& newURL = loader->request().url();
1545
1546     // Log main frame navigation types.
1547     if (m_frame.isMainFrame()) {
1548         if (auto* page = m_frame.page()) {
1549             page->mainFrameLoadStarted(newURL, type);
1550             page->performanceLogging().didReachPointOfInterest(PerformanceLogging::MainFrameLoadStarted);
1551         }
1552     }
1553
1554     policyChecker().setLoadType(type);
1555     bool isFormSubmission = formState;
1556
1557     const String& httpMethod = loader->request().httpMethod();
1558
1559     if (shouldPerformFragmentNavigation(isFormSubmission, httpMethod, policyChecker().loadType(), newURL)) {
1560         RefPtr<DocumentLoader> oldDocumentLoader = m_documentLoader;
1561         NavigationAction action { *m_frame.document(), loader->request(), InitiatedByMainFrame::Unknown, policyChecker().loadType(), isFormSubmission };
1562
1563         oldDocumentLoader->setTriggeringAction(WTFMove(action));
1564         oldDocumentLoader->setLastCheckedRequest(ResourceRequest());
1565         policyChecker().stopCheck();
1566         policyChecker().checkNavigationPolicy(ResourceRequest(loader->request()), ResourceResponse { }  /* redirectResponse */, oldDocumentLoader.get(), WTFMove(formState), [this, protectedFrame = makeRef(m_frame)] (const ResourceRequest& request, WeakPtr<FormState>&&, ShouldContinue shouldContinue) {
1567             continueFragmentScrollAfterNavigationPolicy(request, shouldContinue == ShouldContinue::Yes);
1568         }, PolicyDecisionMode::Synchronous);
1569         return;
1570     }
1571
1572     if (Frame* parent = m_frame.tree().parent())
1573         loader->setOverrideEncoding(parent->loader().documentLoader()->overrideEncoding());
1574
1575     policyChecker().stopCheck();
1576     setPolicyDocumentLoader(loader);
1577     if (loader->triggeringAction().isEmpty())
1578         loader->setTriggeringAction({ *m_frame.document(), loader->request(), InitiatedByMainFrame::Unknown, policyChecker().loadType(), isFormSubmission });
1579
1580     if (Element* ownerElement = m_frame.ownerElement()) {
1581         // We skip dispatching the beforeload event if we've already
1582         // committed a real document load because the event would leak
1583         // subsequent activity by the frame which the parent frame isn't
1584         // supposed to learn. For example, if the child frame navigated to
1585         // a new URL, the parent frame shouldn't learn the URL.
1586         if (!m_stateMachine.committedFirstRealDocumentLoad()
1587             && !ownerElement->dispatchBeforeLoadEvent(loader->request().url().string())) {
1588             continueLoadAfterNavigationPolicy(loader->request(), formState.get(), ShouldContinue::No, allowNavigationToInvalidURL);
1589             return;
1590         }
1591     }
1592
1593     m_frame.navigationScheduler().cancel(true);
1594
1595     if (m_currentLoadShouldBeTreatedAsContinuingLoad) {
1596         continueLoadAfterNavigationPolicy(loader->request(), formState.get(), ShouldContinue::Yes, allowNavigationToInvalidURL);
1597         return;
1598     }
1599
1600     policyChecker().checkNavigationPolicy(ResourceRequest(loader->request()), ResourceResponse { } /* redirectResponse */, loader, WTFMove(formState), [this, protectedFrame = makeRef(m_frame), allowNavigationToInvalidURL, completionHandler = completionHandlerCaller.release()] (const ResourceRequest& request, WeakPtr<FormState>&& formState, ShouldContinue shouldContinue) mutable {
1601         continueLoadAfterNavigationPolicy(request, formState.get(), shouldContinue, allowNavigationToInvalidURL);
1602         completionHandler();
1603     }, PolicyDecisionMode::Asynchronous, shouldSkipSafeBrowsingCheck);
1604 }
1605
1606 void FrameLoader::clearProvisionalLoadForPolicyCheck()
1607 {
1608     if (!m_policyDocumentLoader || !m_provisionalDocumentLoader || m_inClearProvisionalLoadForPolicyCheck)
1609         return;
1610
1611     SetForScope<bool> change(m_inClearProvisionalLoadForPolicyCheck, true);
1612     m_provisionalDocumentLoader->stopLoading();
1613     setProvisionalDocumentLoader(nullptr);
1614 }
1615
1616 void FrameLoader::reportLocalLoadFailed(Frame* frame, const String& url)
1617 {
1618     ASSERT(!url.isEmpty());
1619     if (!frame)
1620         return;
1621
1622     frame->document()->addConsoleMessage(MessageSource::Security, MessageLevel::Error, "Not allowed to load local resource: " + url);
1623 }
1624
1625 void FrameLoader::reportBlockedPortFailed(Frame* frame, const String& url)
1626 {
1627     ASSERT(!url.isEmpty());
1628     if (!frame)
1629         return;
1630     
1631     frame->document()->addConsoleMessage(MessageSource::Security, MessageLevel::Error, "Not allowed to use restricted network port: " + url);
1632 }
1633
1634 void FrameLoader::reportAuthenticationChallengeBlocked(Frame* frame, const URL& url, const String& reason)
1635 {
1636     if (!frame)
1637         return;
1638
1639     frame->document()->addConsoleMessage(MessageSource::Security, MessageLevel::Error, makeString("Blocked ", url.stringCenterEllipsizedToLength(), " from asking for credentials because ", reason, '.'));
1640 }
1641
1642 const ResourceRequest& FrameLoader::initialRequest() const
1643 {
1644     return activeDocumentLoader()->originalRequest();
1645 }
1646
1647 bool FrameLoader::willLoadMediaElementURL(URL& url)
1648 {
1649 #if PLATFORM(IOS)
1650     // MobileStore depends on the iOS 4.0 era client delegate method because webView:resource:willSendRequest:redirectResponse:fromDataSource
1651     // doesn't let them tell when a load request is coming from a media element. See <rdar://problem/8266916> for more details.
1652     if (IOSApplication::isMobileStore())
1653         return m_client.shouldLoadMediaElementURL(url);
1654 #endif
1655
1656     ResourceRequest request(url);
1657
1658     unsigned long identifier;
1659     ResourceError error;
1660     requestFromDelegate(request, identifier, error);
1661     notifier().sendRemainingDelegateMessages(m_documentLoader.get(), identifier, request, ResourceResponse(url, String(), -1, String()), 0, -1, -1, error);
1662
1663     url = request.url();
1664
1665     return error.isNull();
1666 }
1667
1668 bool FrameLoader::shouldReloadToHandleUnreachableURL(DocumentLoader& docLoader)
1669 {
1670     URL unreachableURL = docLoader.unreachableURL();
1671
1672     if (unreachableURL.isEmpty())
1673         return false;
1674
1675     if (!isBackForwardLoadType(policyChecker().loadType()))
1676         return false;
1677
1678     // We only treat unreachableURLs specially during the delegate callbacks
1679     // for provisional load errors and navigation policy decisions. The former
1680     // case handles well-formed URLs that can't be loaded, and the latter
1681     // case handles malformed URLs and unknown schemes. Loading alternate content
1682     // at other times behaves like a standard load.
1683     if (policyChecker().delegateIsDecidingNavigationPolicy() || policyChecker().delegateIsHandlingUnimplementablePolicy())
1684         return m_policyDocumentLoader && unreachableURL == m_policyDocumentLoader->request().url();
1685
1686     return unreachableURL == m_provisionalLoadErrorBeingHandledURL;
1687 }
1688
1689 void FrameLoader::reloadWithOverrideEncoding(const String& encoding)
1690 {
1691     if (!m_documentLoader)
1692         return;
1693
1694     ResourceRequest request = m_documentLoader->request();
1695     URL unreachableURL = m_documentLoader->unreachableURL();
1696     if (!unreachableURL.isEmpty())
1697         request.setURL(unreachableURL);
1698
1699     // FIXME: If the resource is a result of form submission and is not cached, the form will be silently resubmitted.
1700     // We should ask the user for confirmation in this case.
1701     request.setCachePolicy(ResourceRequestCachePolicy::ReturnCacheDataElseLoad);
1702
1703     Ref<DocumentLoader> loader = m_client.createDocumentLoader(request, defaultSubstituteDataForURL(request.url()));
1704     applyShouldOpenExternalURLsPolicyToNewDocumentLoader(m_frame, loader, InitiatedByMainFrame::Unknown, m_documentLoader->shouldOpenExternalURLsPolicyToPropagate());
1705
1706     setPolicyDocumentLoader(loader.ptr());
1707
1708     loader->setOverrideEncoding(encoding);
1709
1710     loadWithDocumentLoader(loader.ptr(), FrameLoadType::Reload, { }, AllowNavigationToInvalidURL::Yes, ShouldTreatAsContinuingLoad::No);
1711 }
1712
1713 void FrameLoader::reload(OptionSet<ReloadOption> options)
1714 {
1715     if (!m_documentLoader)
1716         return;
1717
1718     // If a window is created by javascript, its main frame can have an empty but non-nil URL.
1719     // Reloading in this case will lose the current contents (see 4151001).
1720     if (m_documentLoader->request().url().isEmpty())
1721         return;
1722
1723     // Replace error-page URL with the URL we were trying to reach.
1724     ResourceRequest initialRequest = m_documentLoader->request();
1725     URL unreachableURL = m_documentLoader->unreachableURL();
1726     if (!unreachableURL.isEmpty())
1727         initialRequest.setURL(unreachableURL);
1728
1729     // Create a new document loader for the reload, this will become m_documentLoader eventually,
1730     // but first it has to be the "policy" document loader, and then the "provisional" document loader.
1731     Ref<DocumentLoader> loader = m_client.createDocumentLoader(initialRequest, defaultSubstituteDataForURL(initialRequest.url()));
1732     applyShouldOpenExternalURLsPolicyToNewDocumentLoader(m_frame, loader, InitiatedByMainFrame::Unknown, m_documentLoader->shouldOpenExternalURLsPolicyToPropagate());
1733
1734     loader->setUserContentExtensionsEnabled(!options.contains(ReloadOption::DisableContentBlockers));
1735     
1736     ResourceRequest& request = loader->request();
1737
1738     // FIXME: We don't have a mechanism to revalidate the main resource without reloading at the moment.
1739     request.setCachePolicy(ResourceRequestCachePolicy::ReloadIgnoringCacheData);
1740
1741     addSameSiteInfoToRequestIfNeeded(request);
1742
1743     // If we're about to re-post, set up action so the application can warn the user.
1744     if (request.httpMethod() == "POST")
1745         loader->setTriggeringAction({ *m_frame.document(), request, InitiatedByMainFrame::Unknown, NavigationType::FormResubmitted });
1746
1747     loader->setOverrideEncoding(m_documentLoader->overrideEncoding());
1748
1749     auto frameLoadTypeForReloadOptions = [] (auto options) {
1750         if (options & ReloadOption::FromOrigin)
1751             return FrameLoadType::ReloadFromOrigin;
1752         if (options & ReloadOption::ExpiredOnly)
1753             return FrameLoadType::ReloadExpiredOnly;
1754         return FrameLoadType::Reload;
1755     };
1756     
1757     loadWithDocumentLoader(loader.ptr(), frameLoadTypeForReloadOptions(options), { }, AllowNavigationToInvalidURL::Yes, ShouldTreatAsContinuingLoad::No);
1758 }
1759
1760 void FrameLoader::stopAllLoaders(ClearProvisionalItemPolicy clearProvisionalItemPolicy)
1761 {
1762     ASSERT(!m_frame.document() || m_frame.document()->pageCacheState() != Document::InPageCache);
1763     if (!isStopLoadingAllowed())
1764         return;
1765
1766     // If this method is called from within this method, infinite recursion can occur (3442218). Avoid this.
1767     if (m_inStopAllLoaders)
1768         return;
1769
1770     // This method might dispatch events.
1771     RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(ScriptDisallowedScope::InMainThread::isScriptAllowed());
1772
1773     // Calling stopLoading() on the provisional document loader can blow away
1774     // the frame from underneath.
1775     Ref<Frame> protect(m_frame);
1776
1777     m_inStopAllLoaders = true;
1778
1779     policyChecker().stopCheck();
1780
1781     // If no new load is in progress, we should clear the provisional item from history
1782     // before we call stopLoading.
1783     if (clearProvisionalItemPolicy == ShouldClearProvisionalItem)
1784         history().setProvisionalItem(nullptr);
1785
1786     for (RefPtr<Frame> child = m_frame.tree().firstChild(); child; child = child->tree().nextSibling())
1787         child->loader().stopAllLoaders(clearProvisionalItemPolicy);
1788     if (m_provisionalDocumentLoader)
1789         m_provisionalDocumentLoader->stopLoading();
1790     if (m_documentLoader)
1791         m_documentLoader->stopLoading();
1792
1793     setProvisionalDocumentLoader(nullptr);
1794
1795     m_inStopAllLoaders = false;    
1796 }
1797
1798 void FrameLoader::stopAllLoadersAndCheckCompleteness()
1799 {
1800     stopAllLoaders();
1801
1802     if (!m_checkTimer.isActive())
1803         return;
1804
1805     m_checkTimer.stop();
1806     m_checkingLoadCompleteForDetachment = true;
1807     checkCompletenessNow();
1808     m_checkingLoadCompleteForDetachment = false;
1809 }
1810
1811 void FrameLoader::stopForUserCancel(bool deferCheckLoadComplete)
1812 {
1813     // Calling stopAllLoaders can cause the frame to be deallocated, including the frame loader.
1814     Ref<Frame> protectedFrame(m_frame);
1815
1816     stopAllLoaders();
1817
1818 #if PLATFORM(IOS)
1819     // Lay out immediately when stopping to immediately clear the old page if we just committed this one
1820     // but haven't laid out/painted yet.
1821     // FIXME: Is this behavior specific to iOS? Or should we expose a setting to toggle this behavior?
1822     if (m_frame.view() && !m_frame.view()->didFirstLayout())
1823         m_frame.view()->layoutContext().layout();
1824 #endif
1825
1826     if (deferCheckLoadComplete)
1827         scheduleCheckLoadComplete();
1828     else if (m_frame.page())
1829         checkLoadComplete();
1830 }
1831
1832 DocumentLoader* FrameLoader::activeDocumentLoader() const
1833 {
1834     if (m_state == FrameStateProvisional)
1835         return m_provisionalDocumentLoader.get();
1836     return m_documentLoader.get();
1837 }
1838
1839 bool FrameLoader::isLoading() const
1840 {
1841     DocumentLoader* docLoader = activeDocumentLoader();
1842     if (!docLoader)
1843         return false;
1844     return docLoader->isLoading();
1845 }
1846
1847 bool FrameLoader::frameHasLoaded() const
1848 {
1849     return m_stateMachine.committedFirstRealDocumentLoad() || (m_provisionalDocumentLoader && !m_stateMachine.creatingInitialEmptyDocument()); 
1850 }
1851
1852 void FrameLoader::setDocumentLoader(DocumentLoader* loader)
1853 {
1854     if (!loader && !m_documentLoader)
1855         return;
1856     
1857     ASSERT(loader != m_documentLoader);
1858     ASSERT(!loader || loader->frameLoader() == this);
1859
1860     m_client.prepareForDataSourceReplacement();
1861     detachChildren();
1862
1863     // detachChildren() can trigger this frame's unload event, and therefore
1864     // script can run and do just about anything. For example, an unload event that calls
1865     // document.write("") on its parent frame can lead to a recursive detachChildren()
1866     // invocation for this frame. In that case, we can end up at this point with a
1867     // loader that hasn't been deleted but has been detached from its frame. Such a
1868     // DocumentLoader has been sufficiently detached that we'll end up in an inconsistent
1869     // state if we try to use it.
1870     if (loader && !loader->frame())
1871         return;
1872
1873     if (m_documentLoader)
1874         m_documentLoader->detachFromFrame();
1875
1876     m_documentLoader = loader;
1877 }
1878
1879 void FrameLoader::setPolicyDocumentLoader(DocumentLoader* loader)
1880 {
1881     if (m_policyDocumentLoader == loader)
1882         return;
1883
1884     if (loader)
1885         loader->attachToFrame(m_frame);
1886     if (m_policyDocumentLoader
1887             && m_policyDocumentLoader != m_provisionalDocumentLoader
1888             && m_policyDocumentLoader != m_documentLoader)
1889         m_policyDocumentLoader->detachFromFrame();
1890
1891     m_policyDocumentLoader = loader;
1892 }
1893
1894 void FrameLoader::setProvisionalDocumentLoader(DocumentLoader* loader)
1895 {
1896     ASSERT(!loader || !m_provisionalDocumentLoader);
1897     ASSERT(!loader || loader->frameLoader() == this);
1898
1899     if (m_provisionalDocumentLoader && m_provisionalDocumentLoader != m_documentLoader)
1900         m_provisionalDocumentLoader->detachFromFrame();
1901
1902     m_provisionalDocumentLoader = loader;
1903 }
1904
1905 void FrameLoader::setState(FrameState newState)
1906 {
1907     FrameState oldState = m_state;
1908     m_state = newState;
1909     
1910     if (newState == FrameStateProvisional)
1911         provisionalLoadStarted();
1912     else if (newState == FrameStateComplete) {
1913         frameLoadCompleted();
1914         if (m_documentLoader)
1915             m_documentLoader->stopRecordingResponses();
1916         if (m_frame.isMainFrame() && oldState != newState)
1917             m_frame.page()->performanceLogging().didReachPointOfInterest(PerformanceLogging::MainFrameLoadCompleted);
1918     }
1919 }
1920
1921 void FrameLoader::clearProvisionalLoad()
1922 {
1923     setProvisionalDocumentLoader(nullptr);
1924     m_progressTracker->progressCompleted();
1925     setState(FrameStateComplete);
1926 }
1927
1928 void FrameLoader::commitProvisionalLoad()
1929 {
1930     RefPtr<DocumentLoader> pdl = m_provisionalDocumentLoader;
1931     Ref<Frame> protect(m_frame);
1932
1933     std::unique_ptr<CachedPage> cachedPage;
1934     if (m_loadingFromCachedPage && history().provisionalItem())
1935         cachedPage = PageCache::singleton().take(*history().provisionalItem(), m_frame.page());
1936
1937     LOG(PageCache, "WebCoreLoading %s: About to commit provisional load from previous URL '%s' to new URL '%s' with cached page %p", m_frame.tree().uniqueName().string().utf8().data(),
1938         m_frame.document() ? m_frame.document()->url().stringCenterEllipsizedToLength().utf8().data() : "",
1939         pdl ? pdl->url().stringCenterEllipsizedToLength().utf8().data() : "<no provisional DocumentLoader>", cachedPage.get());
1940
1941     willTransitionToCommitted();
1942
1943     if (!m_frame.tree().parent() && history().currentItem()) {
1944         // Check to see if we need to cache the page we are navigating away from into the back/forward cache.
1945         // We are doing this here because we know for sure that a new page is about to be loaded.
1946         PageCache::singleton().addIfCacheable(*history().currentItem(), m_frame.page());
1947         
1948         WebCore::jettisonExpensiveObjectsOnTopLevelNavigation();
1949     }
1950
1951     if (m_loadType != FrameLoadType::Replace)
1952         closeOldDataSources();
1953
1954     if (!cachedPage && !m_stateMachine.creatingInitialEmptyDocument())
1955         m_client.makeRepresentation(pdl.get());
1956
1957     transitionToCommitted(cachedPage.get());
1958
1959     if (pdl && m_documentLoader) {
1960         // Check if the destination page is allowed to access the previous page's timing information.
1961         Ref<SecurityOrigin> securityOrigin(SecurityOrigin::create(pdl->request().url()));
1962         m_documentLoader->timing().setHasSameOriginAsPreviousDocument(securityOrigin.get().canRequest(m_previousURL));
1963     }
1964
1965     // Call clientRedirectCancelledOrFinished() here so that the frame load delegate is notified that the redirect's
1966     // status has changed, if there was a redirect.  The frame load delegate may have saved some state about
1967     // the redirect in its -webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:.  Since we are
1968     // just about to commit a new page, there cannot possibly be a pending redirect at this point.
1969     if (m_sentRedirectNotification)
1970         clientRedirectCancelledOrFinished(false);
1971     
1972     if (cachedPage && cachedPage->document()) {
1973 #if PLATFORM(IOS)
1974         // FIXME: CachedPage::restore() would dispatch viewport change notification. However UIKit expects load
1975         // commit to happen before any changes to viewport arguments and dealing with this there is difficult.
1976         m_frame.page()->chrome().setDispatchViewportDataDidChangeSuppressed(true);
1977 #endif
1978         willRestoreFromCachedPage();
1979
1980         // Start request for the main resource and dispatch didReceiveResponse before the load is committed for
1981         // consistency with all other loads. See https://bugs.webkit.org/show_bug.cgi?id=150927.
1982         ResourceError mainResouceError;
1983         unsigned long mainResourceIdentifier;
1984         ResourceRequest mainResourceRequest(cachedPage->documentLoader()->request());
1985         requestFromDelegate(mainResourceRequest, mainResourceIdentifier, mainResouceError);
1986         notifier().dispatchDidReceiveResponse(cachedPage->documentLoader(), mainResourceIdentifier, cachedPage->documentLoader()->response());
1987
1988         std::optional<HasInsecureContent> hasInsecureContent = cachedPage->cachedMainFrame()->hasInsecureContent();
1989
1990         // FIXME: This API should be turned around so that we ground CachedPage into the Page.
1991         cachedPage->restore(*m_frame.page());
1992
1993         dispatchDidCommitLoad(hasInsecureContent);
1994
1995 #if PLATFORM(IOS)
1996         m_frame.page()->chrome().setDispatchViewportDataDidChangeSuppressed(false);
1997         m_frame.page()->chrome().dispatchViewportPropertiesDidChange(m_frame.page()->viewportArguments());
1998 #endif
1999         m_frame.page()->chrome().dispatchDisabledAdaptationsDidChange(m_frame.page()->disabledAdaptations());
2000
2001         auto& title = m_documentLoader->title();
2002         if (!title.string.isNull())
2003             m_client.dispatchDidReceiveTitle(title);
2004
2005         // Send remaining notifications for the main resource.
2006         notifier().sendRemainingDelegateMessages(m_documentLoader.get(), mainResourceIdentifier, mainResourceRequest, ResourceResponse(),
2007             nullptr, static_cast<int>(m_documentLoader->response().expectedContentLength()), 0, mainResouceError);
2008
2009         checkCompleted();
2010     } else
2011         didOpenURL();
2012
2013     LOG(Loading, "WebCoreLoading %s: Finished committing provisional load to URL %s", m_frame.tree().uniqueName().string().utf8().data(),
2014         m_frame.document() ? m_frame.document()->url().stringCenterEllipsizedToLength().utf8().data() : "");
2015
2016     if (m_loadType == FrameLoadType::Standard && m_documentLoader && m_documentLoader->isClientRedirect())
2017         history().updateForClientRedirect();
2018
2019     if (m_loadingFromCachedPage) {
2020         // Note, didReceiveDocType is expected to be called for cached pages. See <rdar://problem/5906758> for more details.
2021         if (auto* page = m_frame.page())
2022             page->chrome().didReceiveDocType(m_frame);
2023         m_frame.document()->resume(ReasonForSuspension::PageCache);
2024
2025         // Force a layout to update view size and thereby update scrollbars.
2026 #if PLATFORM(IOS)
2027         if (!m_client.forceLayoutOnRestoreFromPageCache())
2028             m_frame.view()->forceLayout();
2029 #else
2030         m_frame.view()->forceLayout();
2031 #endif
2032
2033         // Main resource delegates were already sent, so we skip the first response here.
2034         for (unsigned i = 1; i < m_documentLoader->responses().size(); ++i) {
2035             const auto& response = m_documentLoader->responses()[i];
2036             // FIXME: If the WebKit client changes or cancels the request, this is not respected.
2037             ResourceError error;
2038             unsigned long identifier;
2039             ResourceRequest request(response.url());
2040             requestFromDelegate(request, identifier, error);
2041             // FIXME: If we get a resource with more than 2B bytes, this code won't do the right thing.
2042             // However, with today's computers and networking speeds, this won't happen in practice.
2043             // Could be an issue with a giant local file.
2044             notifier().sendRemainingDelegateMessages(m_documentLoader.get(), identifier, request, response, 0, static_cast<int>(response.expectedContentLength()), 0, error);
2045         }
2046
2047         // FIXME: Why only this frame and not parent frames?
2048         checkLoadCompleteForThisFrame();
2049     }
2050 }
2051
2052 void FrameLoader::transitionToCommitted(CachedPage* cachedPage)
2053 {
2054     ASSERT(m_client.hasWebView());
2055     ASSERT(m_state == FrameStateProvisional);
2056
2057     if (m_state != FrameStateProvisional)
2058         return;
2059
2060     if (FrameView* view = m_frame.view()) {
2061         if (ScrollAnimator* scrollAnimator = view->existingScrollAnimator())
2062             scrollAnimator->cancelAnimations();
2063     }
2064
2065     m_client.setCopiesOnScroll();
2066     history().updateForCommit();
2067
2068     // The call to closeURL() invokes the unload event handler, which can execute arbitrary
2069     // JavaScript. If the script initiates a new load, we need to abandon the current load,
2070     // or the two will stomp each other.
2071     DocumentLoader* pdl = m_provisionalDocumentLoader.get();
2072     if (m_documentLoader)
2073         closeURL();
2074     if (pdl != m_provisionalDocumentLoader)
2075         return;
2076
2077     if (m_documentLoader)
2078         m_documentLoader->stopLoadingSubresources();
2079     if (m_documentLoader)
2080         m_documentLoader->stopLoadingPlugIns();
2081
2082     // Setting our document loader invokes the unload event handler of our child frames.
2083     // Script can do anything. If the script initiates a new load, we need to abandon the
2084     // current load or the two will stomp each other.
2085     setDocumentLoader(m_provisionalDocumentLoader.get());
2086     if (pdl != m_provisionalDocumentLoader)
2087         return;
2088     setProvisionalDocumentLoader(nullptr);
2089
2090     // Nothing else can interrupt this commit - set the Provisional->Committed transition in stone
2091     setState(FrameStateCommittedPage);
2092
2093     // Handle adding the URL to the back/forward list.
2094     DocumentLoader* dl = m_documentLoader.get();
2095
2096     switch (m_loadType) {
2097     case FrameLoadType::Forward:
2098     case FrameLoadType::Back:
2099     case FrameLoadType::IndexedBackForward:
2100         if (m_frame.page()) {
2101             // If the first load within a frame is a navigation within a back/forward list that was attached
2102             // without any of the items being loaded then we need to update the history in a similar manner as
2103             // for a standard load with the exception of updating the back/forward list (<rdar://problem/8091103>).
2104             if (!m_stateMachine.committedFirstRealDocumentLoad() && m_frame.isMainFrame())
2105                 history().updateForStandardLoad(HistoryController::UpdateAllExceptBackForwardList);
2106
2107             history().updateForBackForwardNavigation();
2108
2109             // For cached pages, CachedFrame::restore will take care of firing the popstate event with the history item's state object
2110             if (history().currentItem() && !cachedPage)
2111                 m_pendingStateObject = history().currentItem()->stateObject();
2112
2113             // Create a document view for this document, or used the cached view.
2114             if (cachedPage) {
2115                 DocumentLoader* cachedDocumentLoader = cachedPage->documentLoader();
2116                 ASSERT(cachedDocumentLoader);
2117                 cachedDocumentLoader->attachToFrame(m_frame);
2118                 m_client.transitionToCommittedFromCachedFrame(cachedPage->cachedMainFrame());
2119             } else
2120                 m_client.transitionToCommittedForNewPage();
2121         }
2122         break;
2123
2124     case FrameLoadType::Reload:
2125     case FrameLoadType::ReloadFromOrigin:
2126     case FrameLoadType::ReloadExpiredOnly:
2127     case FrameLoadType::Same:
2128     case FrameLoadType::Replace:
2129         history().updateForReload();
2130         m_client.transitionToCommittedForNewPage();
2131         break;
2132
2133     case FrameLoadType::Standard:
2134         history().updateForStandardLoad();
2135         if (m_frame.view())
2136             m_frame.view()->setScrollbarsSuppressed(true);
2137         m_client.transitionToCommittedForNewPage();
2138         break;
2139
2140     case FrameLoadType::RedirectWithLockedBackForwardList:
2141         history().updateForRedirectWithLockedBackForwardList();
2142         m_client.transitionToCommittedForNewPage();
2143         break;
2144     }
2145
2146     m_documentLoader->writer().setMIMEType(dl->responseMIMEType());
2147
2148     // Tell the client we've committed this URL.
2149     ASSERT(m_frame.view());
2150
2151     if (m_stateMachine.creatingInitialEmptyDocument())
2152         return;
2153
2154     if (!m_stateMachine.committedFirstRealDocumentLoad())
2155         m_stateMachine.advanceTo(FrameLoaderStateMachine::DisplayingInitialEmptyDocumentPostCommit);
2156 }
2157
2158 void FrameLoader::clientRedirectCancelledOrFinished(bool cancelWithLoadInProgress)
2159 {
2160     // Note that -webView:didCancelClientRedirectForFrame: is called on the frame load delegate even if
2161     // the redirect succeeded.  We should either rename this API, or add a new method, like
2162     // -webView:didFinishClientRedirectForFrame:
2163     m_client.dispatchDidCancelClientRedirect();
2164
2165     if (!cancelWithLoadInProgress)
2166         m_quickRedirectComing = false;
2167
2168     m_sentRedirectNotification = false;
2169 }
2170
2171 void FrameLoader::clientRedirected(const URL& url, double seconds, WallTime fireDate, LockBackForwardList lockBackForwardList)
2172 {
2173     m_client.dispatchWillPerformClientRedirect(url, seconds, fireDate);
2174     
2175     // Remember that we sent a redirect notification to the frame load delegate so that when we commit
2176     // the next provisional load, we can send a corresponding -webView:didCancelClientRedirectForFrame:
2177     m_sentRedirectNotification = true;
2178     
2179     // If a "quick" redirect comes in, we set a special mode so we treat the next
2180     // load as part of the original navigation. If we don't have a document loader, we have
2181     // no "original" load on which to base a redirect, so we treat the redirect as a normal load.
2182     // Loads triggered by JavaScript form submissions never count as quick redirects.
2183     m_quickRedirectComing = (lockBackForwardList == LockBackForwardList::Yes || history().currentItemShouldBeReplaced()) && m_documentLoader && !m_isExecutingJavaScriptFormAction;
2184 }
2185
2186 bool FrameLoader::shouldReload(const URL& currentURL, const URL& destinationURL)
2187 {
2188     // This function implements the rule: "Don't reload if navigating by fragment within
2189     // the same URL, but do reload if going to a new URL or to the same URL with no
2190     // fragment identifier at all."
2191     if (!destinationURL.hasFragmentIdentifier())
2192         return true;
2193     return !equalIgnoringFragmentIdentifier(currentURL, destinationURL);
2194 }
2195
2196 void FrameLoader::closeOldDataSources()
2197 {
2198     // FIXME: Is it important for this traversal to be postorder instead of preorder?
2199     // If so, add helpers for postorder traversal, and use them. If not, then lets not
2200     // use a recursive algorithm here.
2201     for (Frame* child = m_frame.tree().firstChild(); child; child = child->tree().nextSibling())
2202         child->loader().closeOldDataSources();
2203     
2204     if (m_documentLoader)
2205         m_client.dispatchWillClose();
2206
2207     m_client.setMainFrameDocumentReady(false); // stop giving out the actual DOMDocument to observers
2208 }
2209
2210 void FrameLoader::willRestoreFromCachedPage()
2211 {
2212     ASSERT(!m_frame.tree().parent());
2213     ASSERT(m_frame.page());
2214     ASSERT(m_frame.isMainFrame());
2215
2216     m_frame.navigationScheduler().cancel();
2217
2218     // We still have to close the previous part page.
2219     closeURL();
2220     
2221     // Delete old status bar messages (if it _was_ activated on last URL).
2222     if (m_frame.script().canExecuteScripts(NotAboutToExecuteScript)) {
2223         DOMWindow* window = m_frame.document()->domWindow();
2224         window->setStatus(String());
2225         window->setDefaultStatus(String());
2226     }
2227 }
2228
2229 void FrameLoader::open(CachedFrameBase& cachedFrame)
2230 {
2231     m_isComplete = false;
2232     
2233     // Don't re-emit the load event.
2234     m_didCallImplicitClose = true;
2235
2236     URL url = cachedFrame.url();
2237
2238     // FIXME: I suspect this block of code doesn't do anything.
2239     if (url.protocolIsInHTTPFamily() && !url.host().isEmpty() && url.path().isEmpty())
2240         url.setPath("/");
2241
2242     started();
2243     Document* document = cachedFrame.document();
2244     ASSERT(document);
2245     ASSERT(document->domWindow());
2246
2247     clear(document, true, true, cachedFrame.isMainFrame());
2248
2249     document->setPageCacheState(Document::NotInPageCache);
2250
2251     m_needsClear = true;
2252     m_isComplete = false;
2253     m_didCallImplicitClose = false;
2254     m_outgoingReferrer = url.string();
2255
2256     FrameView* view = cachedFrame.view();
2257     
2258     // When navigating to a CachedFrame its FrameView should never be null.  If it is we'll crash in creative ways downstream.
2259     ASSERT(view);
2260     view->setWasScrolledByUser(false);
2261
2262     std::optional<IntRect> previousViewFrameRect = m_frame.view() ?  m_frame.view()->frameRect() : std::optional<IntRect>(std::nullopt);
2263     m_frame.setView(view);
2264
2265     // Use the previous ScrollView's frame rect.
2266     if (previousViewFrameRect)
2267         view->setFrameRect(previousViewFrameRect.value());
2268
2269     {
2270         // Setting the document builds the render tree and runs post style resolution callbacks that can do anything,
2271         // including loading a child frame before its been re-attached to the frame tree as part of this restore.
2272         // For example, the HTML object element may load its content into a frame in a post style resolution callback.
2273         NavigationDisabler disableNavigation { &m_frame };
2274         m_frame.setDocument(document);
2275     }
2276
2277     document->domWindow()->resumeFromDocumentSuspension();
2278
2279     updateFirstPartyForCookies();
2280
2281     cachedFrame.restore();
2282 }
2283
2284 bool FrameLoader::isHostedByObjectElement() const
2285 {
2286     HTMLFrameOwnerElement* owner = m_frame.ownerElement();
2287     return owner && owner->hasTagName(objectTag);
2288 }
2289
2290 bool FrameLoader::isReplacing() const
2291 {
2292     return m_loadType == FrameLoadType::Replace;
2293 }
2294
2295 void FrameLoader::setReplacing()
2296 {
2297     m_loadType = FrameLoadType::Replace;
2298 }
2299
2300 bool FrameLoader::subframeIsLoading() const
2301 {
2302     // It's most likely that the last added frame is the last to load so we walk backwards.
2303     for (Frame* child = m_frame.tree().lastChild(); child; child = child->tree().previousSibling()) {
2304         FrameLoader& childLoader = child->loader();
2305         DocumentLoader* documentLoader = childLoader.documentLoader();
2306         if (documentLoader && documentLoader->isLoadingInAPISense())
2307             return true;
2308         documentLoader = childLoader.provisionalDocumentLoader();
2309         if (documentLoader && documentLoader->isLoadingInAPISense())
2310             return true;
2311         documentLoader = childLoader.policyDocumentLoader();
2312         if (documentLoader)
2313             return true;
2314     }
2315     return false;
2316 }
2317
2318 void FrameLoader::willChangeTitle(DocumentLoader* loader)
2319 {
2320     m_client.willChangeTitle(loader);
2321 }
2322
2323 FrameLoadType FrameLoader::loadType() const
2324 {
2325     return m_loadType;
2326 }
2327     
2328 CachePolicy FrameLoader::subresourceCachePolicy(const URL& url) const
2329 {
2330     if (Page* page = m_frame.page()) {
2331         if (page->isResourceCachingDisabled())
2332             return CachePolicyReload;
2333     }
2334
2335     if (m_isComplete)
2336         return CachePolicyVerify;
2337
2338     if (m_loadType == FrameLoadType::ReloadFromOrigin)
2339         return CachePolicyReload;
2340
2341     if (Frame* parentFrame = m_frame.tree().parent()) {
2342         CachePolicy parentCachePolicy = parentFrame->loader().subresourceCachePolicy(url);
2343         if (parentCachePolicy != CachePolicyVerify)
2344             return parentCachePolicy;
2345     }
2346     
2347     switch (m_loadType) {
2348     case FrameLoadType::Reload:
2349         return CachePolicyRevalidate;
2350     case FrameLoadType::Back:
2351     case FrameLoadType::Forward:
2352     case FrameLoadType::IndexedBackForward:
2353         return CachePolicyHistoryBuffer;
2354     case FrameLoadType::ReloadFromOrigin:
2355         ASSERT_NOT_REACHED(); // Already handled above.
2356         return CachePolicyReload;
2357     case FrameLoadType::RedirectWithLockedBackForwardList:
2358     case FrameLoadType::Replace:
2359     case FrameLoadType::Same:
2360     case FrameLoadType::Standard:
2361         return CachePolicyVerify;
2362     case FrameLoadType::ReloadExpiredOnly:
2363         // We know about expiration for HTTP and data. Do a normal reload otherwise.
2364         if (!url.protocolIsInHTTPFamily() && !url.protocolIsData())
2365             return CachePolicyReload;
2366         return CachePolicyVerify;
2367     }
2368
2369     RELEASE_ASSERT_NOT_REACHED();
2370     return CachePolicyVerify;
2371 }
2372
2373 void FrameLoader::checkLoadCompleteForThisFrame()
2374 {
2375     ASSERT(m_client.hasWebView());
2376
2377     // FIXME: Should this check be done in checkLoadComplete instead of here?
2378     // FIXME: Why does this one check need to be repeated here, and not the many others from checkCompleted?
2379     if (m_frame.document()->isDelayingLoadEvent())
2380         return;
2381
2382     switch (m_state) {
2383         case FrameStateProvisional: {
2384             // FIXME: Prohibiting any provisional load failures from being sent to clients
2385             // while handling provisional load failures is too heavy. For example, the current
2386             // load will fail to cancel another ongoing load. That might prevent clients' page
2387             // load state being handled properly.
2388             if (!m_provisionalLoadErrorBeingHandledURL.isEmpty())
2389                 return;
2390
2391             RefPtr<DocumentLoader> pdl = m_provisionalDocumentLoader;
2392             if (!pdl)
2393                 return;
2394                 
2395             // If we've received any errors we may be stuck in the provisional state and actually complete.
2396             const ResourceError& error = pdl->mainDocumentError();
2397             if (error.isNull())
2398                 return;
2399
2400             // Check all children first.
2401             RefPtr<HistoryItem> item;
2402             if (Page* page = m_frame.page())
2403                 if (isBackForwardLoadType(loadType()))
2404                     // Reset the back forward list to the last committed history item at the top level.
2405                     item = page->mainFrame().loader().history().currentItem();
2406                 
2407             // Only reset if we aren't already going to a new provisional item.
2408             bool shouldReset = !history().provisionalItem();
2409             if (!pdl->isLoadingInAPISense() || pdl->isStopping()) {
2410                 m_provisionalLoadErrorBeingHandledURL = m_provisionalDocumentLoader->url();
2411                 m_client.dispatchDidFailProvisionalLoad(error);
2412 #if ENABLE(CONTENT_FILTERING)
2413                 if (auto contentFilter = pdl->contentFilter())
2414                     contentFilter->handleProvisionalLoadFailure(error);
2415 #endif
2416                 m_provisionalLoadErrorBeingHandledURL = { };
2417
2418                 ASSERT(!pdl->isLoading());
2419
2420                 // If we're in the middle of loading multipart data, we need to restore the document loader.
2421                 if (isReplacing() && !m_documentLoader.get())
2422                     setDocumentLoader(m_provisionalDocumentLoader.get());
2423
2424                 // Finish resetting the load state, but only if another load hasn't been started by the
2425                 // delegate callback.
2426                 if (pdl == m_provisionalDocumentLoader)
2427                     clearProvisionalLoad();
2428                 else if (activeDocumentLoader()) {
2429                     URL unreachableURL = activeDocumentLoader()->unreachableURL();
2430                     if (!unreachableURL.isEmpty() && unreachableURL == pdl->request().url())
2431                         shouldReset = false;
2432                 }
2433             }
2434             if (shouldReset && item)
2435                 if (Page* page = m_frame.page()) {
2436                     page->backForward().setCurrentItem(item.get());
2437                     m_frame.loader().client().updateGlobalHistoryItemForPage();
2438                 }
2439             return;
2440         }
2441         
2442         case FrameStateCommittedPage: {
2443             if (!m_documentLoader)
2444                 return;
2445             if (m_documentLoader->isLoadingInAPISense() && !m_documentLoader->isStopping() && !m_checkingLoadCompleteForDetachment)
2446                 return;
2447
2448             setState(FrameStateComplete);
2449
2450             // FIXME: Is this subsequent work important if we already navigated away?
2451             // Maybe there are bugs because of that, or extra work we can skip because
2452             // the new page is ready.
2453
2454             m_client.forceLayoutForNonHTML();
2455              
2456             // If the user had a scroll point, scroll to it, overriding the anchor point if any.
2457             if (m_frame.page()) {
2458                 if (isBackForwardLoadType(m_loadType) || isReload(m_loadType))
2459                     history().restoreScrollPositionAndViewState();
2460             }
2461
2462             if (m_stateMachine.creatingInitialEmptyDocument() || !m_stateMachine.committedFirstRealDocumentLoad())
2463                 return;
2464
2465             m_progressTracker->progressCompleted();
2466             Page* page = m_frame.page();
2467             if (page) {
2468                 if (m_frame.isMainFrame()) {
2469                     tracePoint(MainResourceLoadDidEnd);
2470                     page->didFinishLoad();
2471                 }
2472             }
2473
2474             const ResourceError& error = m_documentLoader->mainDocumentError();
2475
2476             AXObjectCache::AXLoadingEvent loadingEvent;
2477             if (!error.isNull()) {
2478                 RELEASE_LOG_IF_ALLOWED("checkLoadCompleteForThisFrame: Finished frame load with error (frame = %p, main = %d, isTimeout = %d, isCancellation = %d, errorCode = %d)", &m_frame, m_frame.isMainFrame(), error.isTimeout(), error.isCancellation(), error.errorCode());
2479                 m_client.dispatchDidFailLoad(error);
2480                 loadingEvent = AXObjectCache::AXLoadingFailed;
2481             } else {
2482                 RELEASE_LOG_IF_ALLOWED("checkLoadCompleteForThisFrame: Finished frame load (frame = %p, main = %d)", &m_frame, m_frame.isMainFrame());
2483 #if ENABLE(DATA_DETECTION)
2484                 auto* document = m_frame.document();
2485                 if (m_frame.settings().dataDetectorTypes() != DataDetectorTypeNone && document) {
2486                     if (auto* documentElement = document->documentElement()) {
2487                         RefPtr<Range> documentRange = makeRange(firstPositionInNode(documentElement), lastPositionInNode(documentElement));
2488                         m_frame.setDataDetectionResults(DataDetection::detectContentInRange(documentRange, m_frame.settings().dataDetectorTypes(), m_client.dataDetectionContext()));
2489                         if (m_frame.isMainFrame())
2490                             m_client.dispatchDidFinishDataDetection(m_frame.dataDetectionResults());
2491                     }
2492                 }
2493 #endif
2494                 m_client.dispatchDidFinishLoad();
2495                 loadingEvent = AXObjectCache::AXLoadingFinished;
2496             }
2497
2498             // Notify accessibility.
2499             if (auto* document = m_frame.document()) {
2500                 if (AXObjectCache* cache = document->existingAXObjectCache())
2501                     cache->frameLoadingEventNotification(&m_frame, loadingEvent);
2502             }
2503
2504             // The above calls to dispatchDidFinishLoad() might have detached the Frame
2505             // from its Page and also might have caused Page to be deleted.
2506             // Don't assume 'page' is still available to use.
2507             if (m_frame.isMainFrame() && m_frame.page()) {
2508                 ASSERT(&m_frame.page()->mainFrame() == &m_frame);
2509                 m_frame.page()->diagnosticLoggingClient().logDiagnosticMessageWithResult(DiagnosticLoggingKeys::pageLoadedKey(), emptyString(), error.isNull() ? DiagnosticLoggingResultPass : DiagnosticLoggingResultFail, ShouldSample::Yes);
2510             }
2511
2512             return;
2513         }
2514         
2515         case FrameStateComplete:
2516             m_loadType = FrameLoadType::Standard;
2517             frameLoadCompleted();
2518             return;
2519     }
2520
2521     ASSERT_NOT_REACHED();
2522 }
2523
2524 void FrameLoader::setOriginalURLForDownloadRequest(ResourceRequest& request)
2525 {
2526     // FIXME: Rename firstPartyForCookies back to mainDocumentURL. It was a mistake to think that it was only used for cookies.
2527     // The originalURL is defined as the URL of the page where the download was initiated.
2528     URL originalURL;
2529     auto* initiator = m_frame.document();
2530     if (initiator) {
2531         originalURL = initiator->firstPartyForCookies();
2532         // If there is no main document URL, it means that this document is newly opened and just for download purpose.
2533         // In this case, we need to set the originalURL to this document's opener's main document URL.
2534         if (originalURL.isEmpty() && opener() && opener()->document()) {
2535             originalURL = opener()->document()->firstPartyForCookies();
2536             initiator = opener()->document();
2537         }
2538     }
2539     // If the originalURL is the same as the requested URL, we are processing a download
2540     // initiated directly without a page and do not need to specify the originalURL.
2541     if (originalURL == request.url())
2542         request.setFirstPartyForCookies(URL());
2543     else
2544         request.setFirstPartyForCookies(originalURL);
2545     addSameSiteInfoToRequestIfNeeded(request, initiator);
2546 }
2547
2548 void FrameLoader::didReachLayoutMilestone(LayoutMilestones milestones)
2549 {
2550     ASSERT(m_frame.isMainFrame());
2551
2552     m_client.dispatchDidReachLayoutMilestone(milestones);
2553 }
2554
2555 void FrameLoader::didFirstLayout()
2556 {
2557 #if PLATFORM(IOS)
2558     // Only send layout-related delegate callbacks synchronously for the main frame to
2559     // avoid reentering layout for the main frame while delivering a layout-related delegate
2560     // callback for a subframe.
2561     if (&m_frame != &m_frame.page()->mainFrame())
2562         return;
2563 #endif
2564     if (m_frame.page() && isBackForwardLoadType(m_loadType))
2565         history().restoreScrollPositionAndViewState();
2566
2567     if (m_stateMachine.committedFirstRealDocumentLoad() && !m_stateMachine.isDisplayingInitialEmptyDocument() && !m_stateMachine.firstLayoutDone())
2568         m_stateMachine.advanceTo(FrameLoaderStateMachine::FirstLayoutDone);
2569 }
2570
2571 void FrameLoader::frameLoadCompleted()
2572 {
2573     // Note: Can be called multiple times.
2574
2575     m_client.frameLoadCompleted();
2576
2577     history().updateForFrameLoadCompleted();
2578
2579     // After a canceled provisional load, firstLayoutDone is false.
2580     // Reset it to true if we're displaying a page.
2581     if (m_documentLoader && m_stateMachine.committedFirstRealDocumentLoad() && !m_stateMachine.isDisplayingInitialEmptyDocument() && !m_stateMachine.firstLayoutDone())
2582         m_stateMachine.advanceTo(FrameLoaderStateMachine::FirstLayoutDone);
2583 }
2584
2585 void FrameLoader::detachChildren()
2586 {
2587     // detachChildren() will fire the unload event in each subframe and the
2588     // HTML specification states that the parent document's ignore-opens-during-unload counter while
2589     // this event is being fired in its subframes:
2590     // https://html.spec.whatwg.org/multipage/browsers.html#unload-a-document
2591     IgnoreOpensDuringUnloadCountIncrementer ignoreOpensDuringUnloadCountIncrementer(m_frame.document());
2592
2593     // Any subframe inserted by unload event handlers executed in the loop below will not get unloaded
2594     // because we create a copy of the subframes list before looping. Therefore, it would be unsafe to
2595     // allow loading of subframes at this point.
2596     SubframeLoadingDisabler subframeLoadingDisabler(m_frame.document());
2597
2598     Vector<Ref<Frame>, 16> childrenToDetach;
2599     childrenToDetach.reserveInitialCapacity(m_frame.tree().childCount());
2600     for (Frame* child = m_frame.tree().lastChild(); child; child = child->tree().previousSibling())
2601         childrenToDetach.uncheckedAppend(*child);
2602     for (auto& child : childrenToDetach)
2603         child->loader().detachFromParent();
2604 }
2605
2606 void FrameLoader::closeAndRemoveChild(Frame& child)
2607 {
2608     child.tree().detachFromParent();
2609
2610     child.setView(nullptr);
2611     if (child.ownerElement() && child.page())
2612         child.page()->decrementSubframeCount();
2613     child.willDetachPage();
2614     child.detachFromPage();
2615
2616     m_frame.tree().removeChild(child);
2617 }
2618
2619 // Called every time a resource is completely loaded or an error is received.
2620 void FrameLoader::checkLoadComplete()
2621 {
2622     m_shouldCallCheckLoadComplete = false;
2623
2624     if (!m_frame.page())
2625         return;
2626
2627     ASSERT(m_client.hasWebView());
2628     
2629     // FIXME: Always traversing the entire frame tree is a bit inefficient, but 
2630     // is currently needed in order to null out the previous history item for all frames.
2631     Vector<Ref<Frame>, 16> frames;
2632     for (Frame* frame = &m_frame.mainFrame(); frame; frame = frame->tree().traverseNext())
2633         frames.append(*frame);
2634
2635     // To process children before their parents, iterate the vector backwards.
2636     for (auto frame = frames.rbegin(); frame != frames.rend(); ++frame) {
2637         if ((*frame)->page())
2638             (*frame)->loader().checkLoadCompleteForThisFrame();
2639     }
2640 }
2641
2642 int FrameLoader::numPendingOrLoadingRequests(bool recurse) const
2643 {
2644     if (!recurse)
2645         return m_frame.document()->cachedResourceLoader().requestCount();
2646
2647     int count = 0;
2648     for (Frame* frame = &m_frame; frame; frame = frame->tree().traverseNext(&m_frame))
2649         count += frame->document()->cachedResourceLoader().requestCount();
2650     return count;
2651 }
2652
2653 String FrameLoader::userAgent(const URL& url) const
2654 {
2655     return m_client.userAgent(url);
2656 }
2657
2658 void FrameLoader::dispatchOnloadEvents()
2659 {
2660     m_client.dispatchDidDispatchOnloadEvents();
2661
2662     if (documentLoader())
2663         documentLoader()->dispatchOnloadEvents();
2664 }
2665
2666 void FrameLoader::frameDetached()
2667 {
2668     // Calling stopAllLoadersAndCheckCompleteness() can cause the frame to be deallocated, including the frame loader.
2669     Ref<Frame> protectedFrame(m_frame);
2670
2671     if (m_checkTimer.isActive()) {
2672         m_checkTimer.stop();
2673         checkCompletenessNow();
2674     }
2675
2676     if (m_frame.document()->pageCacheState() != Document::InPageCache) {
2677         stopAllLoadersAndCheckCompleteness();
2678         m_frame.document()->stopActiveDOMObjects();
2679     }
2680
2681     detachFromParent();
2682 }
2683
2684 void FrameLoader::detachFromParent()
2685 {
2686     // Calling stopAllLoaders() can cause the frame to be deallocated, including the frame loader.
2687     Ref<Frame> protect(m_frame);
2688
2689     closeURL();
2690     history().saveScrollPositionAndViewStateToItem(history().currentItem());
2691     detachChildren();
2692     if (m_frame.document()->pageCacheState() != Document::InPageCache) {
2693         // stopAllLoaders() needs to be called after detachChildren() if the document is not in the page cache,
2694         // because detachedChildren() will trigger the unload event handlers of any child frames, and those event
2695         // handlers might start a new subresource load in this frame.
2696         stopAllLoaders();
2697     }
2698
2699     InspectorInstrumentation::frameDetachedFromParent(m_frame);
2700
2701     detachViewsAndDocumentLoader();
2702
2703     m_progressTracker = nullptr;
2704
2705     if (Frame* parent = m_frame.tree().parent()) {
2706         parent->loader().closeAndRemoveChild(m_frame);
2707         parent->loader().scheduleCheckCompleted();
2708         parent->loader().scheduleCheckLoadComplete();
2709     } else {
2710         m_frame.setView(nullptr);
2711         m_frame.willDetachPage();
2712         m_frame.detachFromPage();
2713     }
2714 }
2715
2716 void FrameLoader::detachViewsAndDocumentLoader()
2717 {
2718     m_client.detachedFromParent2();
2719     setDocumentLoader(nullptr);
2720     m_client.detachedFromParent3();
2721 }
2722     
2723 void FrameLoader::addExtraFieldsToSubresourceRequest(ResourceRequest& request)
2724 {
2725     addExtraFieldsToRequest(request, m_loadType, false);
2726 }
2727
2728 void FrameLoader::addExtraFieldsToMainResourceRequest(ResourceRequest& request)
2729 {
2730     // FIXME: Using m_loadType seems wrong for some callers.
2731     // If we are only preparing to load the main resource, that is previous load's load type!
2732     addExtraFieldsToRequest(request, m_loadType, true);
2733
2734     // Upgrade-Insecure-Requests should only be added to main resource requests
2735     addHTTPUpgradeInsecureRequestsIfNeeded(request);
2736 }
2737
2738 ResourceRequestCachePolicy FrameLoader::defaultRequestCachingPolicy(const ResourceRequest& request, FrameLoadType loadType, bool isMainResource)
2739 {
2740     if (m_overrideCachePolicyForTesting)
2741         return m_overrideCachePolicyForTesting.value();
2742
2743     if (isMainResource) {
2744         if (isReload(loadType) || request.isConditional())
2745             return ResourceRequestCachePolicy::ReloadIgnoringCacheData;
2746
2747         return ResourceRequestCachePolicy::UseProtocolCachePolicy;
2748     }
2749
2750     if (request.isConditional())
2751         return ResourceRequestCachePolicy::ReloadIgnoringCacheData;
2752
2753     if (documentLoader()->isLoadingInAPISense()) {
2754         // If we inherit cache policy from a main resource, we use the DocumentLoader's
2755         // original request cache policy for two reasons:
2756         // 1. For POST requests, we mutate the cache policy for the main resource,
2757         //    but we do not want this to apply to subresources
2758         // 2. Delegates that modify the cache policy using willSendRequest: should
2759         //    not affect any other resources. Such changes need to be done
2760         //    per request.
2761         ResourceRequestCachePolicy mainDocumentOriginalCachePolicy = documentLoader()->originalRequest().cachePolicy();
2762         // Back-forward navigations try to load main resource from cache only to avoid re-submitting form data, and start over (with a warning dialog) if that fails.
2763         // This policy is set on initial request too, but should not be inherited.
2764         return (mainDocumentOriginalCachePolicy == ResourceRequestCachePolicy::ReturnCacheDataDontLoad) ? ResourceRequestCachePolicy::ReturnCacheDataElseLoad : mainDocumentOriginalCachePolicy;
2765     }
2766
2767     return ResourceRequestCachePolicy::UseProtocolCachePolicy;
2768 }
2769
2770 void FrameLoader::addExtraFieldsToRequest(ResourceRequest& request, FrameLoadType loadType, bool isMainResource)
2771 {
2772     if (m_currentLoadShouldBeTreatedAsContinuingLoad)
2773         return;
2774
2775     // Don't set the cookie policy URL if it's already been set.
2776     // But make sure to set it on all requests regardless of protocol, as it has significance beyond the cookie policy (<rdar://problem/6616664>).
2777     if (request.firstPartyForCookies().isEmpty()) {
2778         if (isMainResource && m_frame.isMainFrame())
2779             request.setFirstPartyForCookies(request.url());
2780         else if (Document* document = m_frame.document())
2781             request.setFirstPartyForCookies(document->firstPartyForCookies());
2782     }
2783
2784     if (request.isSameSiteUnspecified()) {
2785         auto* initiator = m_frame.document();
2786         if (isMainResource) {
2787             auto* ownerFrame = m_frame.tree().parent();
2788             if (!ownerFrame && m_stateMachine.isDisplayingInitialEmptyDocument())
2789                 ownerFrame = m_opener;
2790             if (ownerFrame)
2791                 initiator = ownerFrame->document();
2792             ASSERT(ownerFrame || m_frame.isMainFrame());
2793         }
2794         addSameSiteInfoToRequestIfNeeded(request, initiator);
2795         request.setIsTopSite(isMainResource && m_frame.isMainFrame());
2796     }
2797
2798     Page* page = frame().page();
2799     bool hasSpecificCachePolicy = request.cachePolicy() != ResourceRequestCachePolicy::UseProtocolCachePolicy;
2800
2801     if (page && page->isResourceCachingDisabled()) {
2802         request.setCachePolicy(ResourceRequestCachePolicy::ReloadIgnoringCacheData);
2803         loadType = FrameLoadType::ReloadFromOrigin;
2804     } else if (!hasSpecificCachePolicy)
2805         request.setCachePolicy(defaultRequestCachingPolicy(request, loadType, isMainResource));
2806
2807     // The remaining modifications are only necessary for HTTP and HTTPS.
2808     if (!request.url().isEmpty() && !request.url().protocolIsInHTTPFamily())
2809         return;
2810
2811     if (!hasSpecificCachePolicy && request.cachePolicy() == ResourceRequestCachePolicy::ReloadIgnoringCacheData) {
2812         if (loadType == FrameLoadType::Reload)
2813             request.setHTTPHeaderField(HTTPHeaderName::CacheControl, "max-age=0");
2814         else if (loadType == FrameLoadType::ReloadFromOrigin) {
2815             request.setHTTPHeaderField(HTTPHeaderName::CacheControl, "no-cache");
2816             request.setHTTPHeaderField(HTTPHeaderName::Pragma, "no-cache");
2817         }
2818     }
2819
2820     if (m_overrideResourceLoadPriorityForTesting)
2821         request.setPriority(m_overrideResourceLoadPriorityForTesting.value());
2822
2823     applyUserAgentIfNeeded(request);
2824
2825     if (isMainResource)
2826         request.setHTTPAccept(defaultAcceptHeader);
2827
2828     // Make sure we send the Origin header.
2829     addHTTPOriginIfNeeded(request, String());
2830
2831     // Only set fallback array if it's still empty (later attempts may be incorrect, see bug 117818).
2832     if (request.responseContentDispositionEncodingFallbackArray().isEmpty()) {
2833         // Always try UTF-8. If that fails, try frame encoding (if any) and then the default.
2834         request.setResponseContentDispositionEncodingFallbackArray("UTF-8", m_frame.document()->encoding(), m_frame.settings().defaultTextEncodingName());
2835     }
2836 }
2837
2838 void FrameLoader::addHTTPOriginIfNeeded(ResourceRequest& request, const String& origin)
2839 {
2840     if (!request.httpOrigin().isEmpty())
2841         return;  // Request already has an Origin header.
2842
2843     // Don't send an Origin header for GET or HEAD to avoid privacy issues.
2844     // For example, if an intranet page has a hyperlink to an external web
2845     // site, we don't want to include the Origin of the request because it
2846     // will leak the internal host name. Similar privacy concerns have lead
2847     // to the widespread suppression of the Referer header at the network
2848     // layer.
2849     if (request.httpMethod() == "GET" || request.httpMethod() == "HEAD")
2850         return;
2851
2852     // For non-GET and non-HEAD methods, always send an Origin header so the
2853     // server knows we support this feature.
2854
2855     if (origin.isEmpty()) {
2856         // If we don't know what origin header to attach, we attach the value
2857         // for an empty origin.
2858         request.setHTTPOrigin(SecurityOrigin::createUnique()->toString());
2859         return;
2860     }
2861
2862     request.setHTTPOrigin(origin);
2863 }
2864
2865 // Implements the "'Same-site' and 'cross-site' Requests" algorithm from <https://tools.ietf.org/html/draft-ietf-httpbis-cookie-same-site-00#section-2.1>.
2866 // The algorithm is ammended to treat URLs that inherit their security origin from their owner (e.g. about:blank)
2867 // as same-site. This matches the behavior of Chrome and Firefox.
2868 void FrameLoader::addSameSiteInfoToRequestIfNeeded(ResourceRequest& request, const Document* initiator)
2869 {
2870     if (!request.isSameSiteUnspecified())
2871         return;
2872     if (!initiator) {
2873         request.setIsSameSite(true);
2874         return;
2875     }
2876     if (SecurityPolicy::shouldInheritSecurityOriginFromOwner(request.url())) {
2877         request.setIsSameSite(true);
2878         return;
2879     }
2880     request.setIsSameSite(registrableDomainsAreEqual(initiator->siteForCookies(), request.url()));
2881 }
2882
2883 void FrameLoader::addHTTPUpgradeInsecureRequestsIfNeeded(ResourceRequest& request)
2884 {
2885     if (request.url().protocolIs("https")) {
2886         // FIXME: Identify HSTS cases and avoid adding the header. <https://bugs.webkit.org/show_bug.cgi?id=157885>
2887         return;
2888     }
2889
2890     request.setHTTPHeaderField(HTTPHeaderName::UpgradeInsecureRequests, "1"_s);
2891 }
2892
2893 void FrameLoader::loadPostRequest(FrameLoadRequest&& request, const String& referrer, FrameLoadType loadType, Event* event, RefPtr<FormState>&& formState, CompletionHandler<void()>&& completionHandler)
2894 {
2895     String frameName = request.frameName();
2896     LockHistory lockHistory = request.lockHistory();
2897     AllowNavigationToInvalidURL allowNavigationToInvalidURL = request.allowNavigationToInvalidURL();
2898     NewFrameOpenerPolicy openerPolicy = request.newFrameOpenerPolicy();
2899
2900     const ResourceRequest& inRequest = request.resourceRequest();
2901     const URL& url = inRequest.url();
2902     const String& contentType = inRequest.httpContentType();
2903     String origin = inRequest.httpOrigin();
2904
2905     ResourceRequest workingResourceRequest(url);    
2906
2907     if (!referrer.isEmpty())
2908         workingResourceRequest.setHTTPReferrer(referrer);
2909     workingResourceRequest.setHTTPOrigin(origin);
2910     workingResourceRequest.setHTTPMethod("POST");
2911     workingResourceRequest.setHTTPBody(inRequest.httpBody());
2912     workingResourceRequest.setHTTPContentType(contentType);
2913     addExtraFieldsToRequest(workingResourceRequest, loadType, true);
2914
2915     if (Document* document = m_frame.document())
2916         document->contentSecurityPolicy()->upgradeInsecureRequestIfNeeded(workingResourceRequest, ContentSecurityPolicy::InsecureRequestType::Load);
2917
2918     NavigationAction action { request.requester(), workingResourceRequest, request.initiatedByMainFrame(), loadType, true, event, request.shouldOpenExternalURLsPolicy(), request.downloadAttribute() };
2919
2920     if (!frameName.isEmpty()) {
2921         // The search for a target frame is done earlier in the case of form submission.
2922         if (auto* targetFrame = formState ? nullptr : findFrameForNavigation(frameName)) {
2923             targetFrame->loader().loadWithNavigationAction(workingResourceRequest, WTFMove(action), lockHistory, loadType, WTFMove(formState), allowNavigationToInvalidURL, ShouldSkipSafeBrowsingCheck::No, WTFMove(completionHandler));
2924             return;
2925         }
2926
2927         policyChecker().checkNewWindowPolicy(WTFMove(action), WTFMove(workingResourceRequest), WTFMove(formState), frameName, [this, allowNavigationToInvalidURL, openerPolicy, completionHandler = WTFMove(completionHandler)] (const ResourceRequest& request, WeakPtr<FormState>&& formState, const String& frameName, const NavigationAction& action, ShouldContinue shouldContinue) mutable {
2928             continueLoadAfterNewWindowPolicy(request, formState.get(), frameName, action, shouldContinue, allowNavigationToInvalidURL, openerPolicy);
2929             completionHandler();
2930         });
2931         return;
2932     }
2933
2934     // must grab this now, since this load may stop the previous load and clear this flag
2935     bool isRedirect = m_quickRedirectComing;
2936     loadWithNavigationAction(workingResourceRequest, WTFMove(action), lockHistory, loadType, WTFMove(formState), allowNavigationToInvalidURL, request.shouldSkipSafeBrowsingCheck(), [this, isRedirect, protectedFrame = makeRef(m_frame), completionHandler = WTFMove(completionHandler)] () mutable {
2937         if (isRedirect) {
2938             m_quickRedirectComing = false;
2939             if (m_provisionalDocumentLoader)
2940                 m_provisionalDocumentLoader->setIsClientRedirect(true);
2941             else if (m_policyDocumentLoader)
2942                 m_policyDocumentLoader->setIsClientRedirect(true);
2943         }
2944         completionHandler();
2945     });
2946 }
2947
2948 unsigned long FrameLoader::loadResourceSynchronously(const ResourceRequest& request, ClientCredentialPolicy clientCredentialPolicy, const FetchOptions& options, const HTTPHeaderMap& originalRequestHeaders, ResourceError& error, ResourceResponse& response, RefPtr<SharedBuffer>& data)
2949 {
2950     ASSERT(m_frame.document());
2951     String referrer = SecurityPolicy::generateReferrerHeader(m_frame.document()->referrerPolicy(), request.url(), outgoingReferrer());
2952     
2953     ResourceRequest initialRequest = request;
2954     initialRequest.setTimeoutInterval(10);
2955     
2956     if (!referrer.isEmpty())
2957         initialRequest.setHTTPReferrer(referrer);
2958     addHTTPOriginIfNeeded(initialRequest, outgoingOrigin());
2959
2960     initialRequest.setFirstPartyForCookies(m_frame.mainFrame().loader().documentLoader()->request().url());
2961     
2962     addExtraFieldsToSubresourceRequest(initialRequest);
2963
2964     unsigned long identifier = 0;    
2965     ResourceRequest newRequest(initialRequest);
2966     requestFromDelegate(newRequest, identifier, error);
2967
2968 #if ENABLE(CONTENT_EXTENSIONS)
2969     if (error.isNull()) {
2970         if (auto* page = m_frame.page()) {
2971             if (m_documentLoader) {
2972                 auto blockedStatus = page->userContentProvider().processContentExtensionRulesForLoad(newRequest.url(), ResourceType::Raw, *m_documentLoader);
2973                 applyBlockedStatusToRequest(blockedStatus, page, newRequest);
2974                 if (blockedStatus.blockedLoad) {
2975                     newRequest = { };
2976                     error = ResourceError(errorDomainWebKitInternal, 0, initialRequest.url(), emptyString());
2977                     response = { };
2978                     data = nullptr;
2979                 }
2980             }
2981         }
2982     }
2983 #endif
2984
2985     m_frame.document()->contentSecurityPolicy()->upgradeInsecureRequestIfNeeded(newRequest, ContentSecurityPolicy::InsecureRequestType::Load);
2986     
2987     if (error.isNull()) {
2988         ASSERT(!newRequest.isNull());
2989
2990         if (!documentLoader()->applicationCacheHost().maybeLoadSynchronously(newRequest, error, response, data)) {
2991             Vector<char> buffer;
2992             platformStrategies()->loaderStrategy()->loadResourceSynchronously(*this, identifier, newRequest, clientCredentialPolicy, options, originalRequestHeaders, error, response, buffer);
2993             data = SharedBuffer::create(WTFMove(buffer));
2994             documentLoader()->applicationCacheHost().maybeLoadFallbackSynchronously(newRequest, error, response, data);
2995             ResourceLoadObserver::shared().logSubresourceLoading(&m_frame, newRequest, response);
2996         }
2997     }
2998     notifier().sendRemainingDelegateMessages(m_documentLoader.get(), identifier, request, response, data ? data->data() : nullptr, data ? data->size() : 0, -1, error);
2999     return identifier;
3000 }
3001
3002 const ResourceRequest& FrameLoader::originalRequest() const
3003 {
3004     return activeDocumentLoader()->originalRequestCopy();
3005 }
3006
3007 void FrameLoader::receivedMainResourceError(const ResourceError& error)
3008 {
3009     // Retain because the stop may release the last reference to it.
3010     Ref<Frame> protect(m_frame);
3011
3012     RefPtr<DocumentLoader> loader = activeDocumentLoader();
3013     // FIXME: Don't want to do this if an entirely new load is going, so should check
3014     // that both data sources on the frame are either this or nil.
3015     stop();
3016     if (m_client.shouldFallBack(error))
3017         handleFallbackContent();
3018
3019     if (m_state == FrameStateProvisional && m_provisionalDocumentLoader) {
3020         if (m_submittedFormURL == m_provisionalDocumentLoader->originalRequestCopy().url())
3021             m_submittedFormURL = URL();
3022             
3023         // We might have made a page cache item, but now we're bailing out due to an error before we ever
3024         // transitioned to the new page (before WebFrameState == commit).  The goal here is to restore any state
3025         // so that the existing view (that wenever got far enough to replace) can continue being used.
3026         history().invalidateCurrentItemCachedPage();
3027         
3028         // Call clientRedirectCancelledOrFinished here so that the frame load delegate is notified that the redirect's
3029         // status has changed, if there was a redirect. The frame load delegate may have saved some state about
3030         // the redirect in its -webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:. Since we are definitely
3031         // not going to use this provisional resource, as it was cancelled, notify the frame load delegate that the redirect
3032         // has ended.
3033         if (m_sentRedirectNotification)
3034             clientRedirectCancelledOrFinished(false);
3035     }
3036
3037     checkCompleted();
3038     if (m_frame.page())
3039         checkLoadComplete();
3040 }
3041
3042 void FrameLoader::continueFragmentScrollAfterNavigationPolicy(const ResourceRequest& request, bool shouldContinue)
3043 {
3044     m_quickRedirectComing = false;
3045
3046     if (!shouldContinue)
3047         return;
3048
3049     // Calling stopLoading() on the provisional document loader can cause the underlying
3050     // frame to be deallocated.
3051     Ref<Frame> protectedFrame(m_frame);
3052
3053     // If we have a provisional request for a different document, a fragment scroll should cancel it.
3054     if (m_provisionalDocumentLoader && !equalIgnoringFragmentIdentifier(m_provisionalDocumentLoader->request().url(), request.url())) {
3055         m_provisionalDocumentLoader->stopLoading();
3056         setProvisionalDocumentLoader(nullptr);
3057     }
3058
3059     bool isRedirect = m_quickRedirectComing || policyChecker().loadType() == FrameLoadType::RedirectWithLockedBackForwardList;
3060     loadInSameDocument(request.url(), 0, !isRedirect);
3061 }
3062
3063 bool FrameLoader::shouldPerformFragmentNavigation(bool isFormSubmission, const String& httpMethod, FrameLoadType loadType, const URL& url)
3064 {
3065     // We don't do this if we are submitting a form with method other than "GET", explicitly reloading,
3066     // currently displaying a frameset, or if the URL does not have a fragment.
3067     // These rules were originally based on what KHTML was doing in KHTMLPart::openURL.
3068
3069     // FIXME: What about load types other than Standard and Reload?
3070
3071     return (!isFormSubmission || equalLettersIgnoringASCIICase(httpMethod, "get"))
3072         && !isReload(loadType)
3073         && loadType != FrameLoadType::Same
3074         && !shouldReload(m_frame.document()->url(), url)
3075         // We don't want to just scroll if a link from within a
3076         // frameset is trying to reload the frameset into _top.
3077         && !m_frame.document()->isFrameSet();
3078 }
3079
3080 static bool itemAllowsScrollRestoration(HistoryItem* historyItem)
3081 {
3082     return !historyItem || historyItem->shouldRestoreScrollPosition();
3083 }
3084
3085 static bool isSameDocumentReload(bool isNewNavigation, FrameLoadType loadType)
3086 {
3087     return !isNewNavigation && !isBackForwardLoadType(loadType);
3088 }
3089
3090 void FrameLoader::scrollToFragmentWithParentBoundary(const URL& url, bool isNewNavigation)
3091 {
3092     FrameView* view = m_frame.view();
3093     if (!view)
3094         return;
3095
3096     if (isSameDocumentReload(isNewNavigation, m_loadType) || itemAllowsScrollRestoration(history().currentItem()))
3097         view->scrollToFragment(url);
3098 }
3099
3100 bool FrameLoader::shouldClose()
3101 {
3102     Page* page = m_frame.page();
3103     if (!page)
3104         return true;
3105     if (!page->chrome().canRunBeforeUnloadConfirmPanel())
3106         return true;
3107
3108     // Store all references to each subframe in advance since beforeunload's event handler may modify frame
3109     Vector<Ref<Frame>, 16> targetFrames;
3110     targetFrames.append(m_frame);
3111     for (Frame* child = m_frame.tree().firstChild(); child; child = child->tree().traverseNext(&m_frame))
3112         targetFrames.append(*child);
3113
3114     bool shouldClose = false;
3115     {
3116         NavigationDisabler navigationDisabler(&m_frame);
3117         IgnoreOpensDuringUnloadCountIncrementer ignoreOpensDuringUnloadCountIncrementer(m_frame.document());
3118         size_t i;
3119
3120         for (i = 0; i < targetFrames.size(); i++) {
3121             if (!targetFrames[i]->tree().isDescendantOf(&m_frame))
3122                 continue;
3123             if (!targetFrames[i]->loader().dispatchBeforeUnloadEvent(page->chrome(), this))
3124                 break;
3125         }
3126
3127         if (i == targetFrames.size())
3128             shouldClose = true;
3129     }
3130
3131     if (!shouldClose)
3132         m_submittedFormURL = URL();
3133
3134     m_currentNavigationHasShownBeforeUnloadConfirmPanel = false;
3135     return shouldClose;
3136 }
3137
3138 void FrameLoader::dispatchUnloadEvents(UnloadEventPolicy unloadEventPolicy)
3139 {
3140     if (!m_frame.document())
3141         return;
3142
3143     // We store the frame's page in a local variable because the frame might get detached inside dispatchEvent.
3144     ForbidPromptsScope forbidPrompts(m_frame.page());
3145     IgnoreOpensDuringUnloadCountIncrementer ignoreOpensDuringUnloadCountIncrementer(m_frame.document());
3146
3147     if (m_didCallImplicitClose && !m_wasUnloadEventEmitted) {
3148         auto* currentFocusedElement = m_frame.document()->focusedElement();
3149         if (is<HTMLInputElement>(currentFocusedElement))
3150             downcast<HTMLInputElement>(*currentFocusedElement).endEditing();
3151         if (m_pageDismissalEventBeingDispatched == PageDismissalType::None) {
3152             if (unloadEventPolicy == UnloadEventPolicyUnloadAndPageHide) {
3153                 m_pageDismissalEventBeingDispatched = PageDismissalType::PageHide;
3154                 m_frame.document()->domWindow()->dispatchEvent(PageTransitionEvent::create(eventNames().pagehideEvent, m_frame.document()->pageCacheState() == Document::AboutToEnterPageCache), m_frame.document());
3155             }
3156
3157             // FIXME: update Page Visibility state here.
3158             // https://bugs.webkit.org/show_bug.cgi?id=116770
3159
3160             if (m_frame.document()->pageCacheState() == Document::NotInPageCache) {
3161                 Ref<Event> unloadEvent(Event::create(eventNames().unloadEvent, Event::CanBubble::No, Event::IsCancelable::No));
3162                 // The DocumentLoader (and thus its LoadTiming) might get destroyed
3163                 // while dispatching the event, so protect it to prevent writing the end
3164                 // time into freed memory.
3165                 RefPtr<DocumentLoader> documentLoader = m_provisionalDocumentLoader;
3166                 m_pageDismissalEventBeingDispatched = PageDismissalType::Unload;
3167                 if (documentLoader && documentLoader->timing().startTime() && !documentLoader->timing().unloadEventStart() && !documentLoader->timing().unloadEventEnd()) {
3168                     auto& timing = documentLoader->timing();
3169                     timing.markUnloadEventStart();
3170                     m_frame.document()->domWindow()->dispatchEvent(unloadEvent, m_frame.document());
3171                     timing.markUnloadEventEnd();
3172                 } else
3173                     m_frame.document()->domWindow()->dispatchEvent(unloadEvent, m_frame.document());
3174             }
3175         }
3176         m_pageDismissalEventBeingDispatched = PageDismissalType::None;
3177         m_wasUnloadEventEmitted = true;
3178     }
3179
3180     // Dispatching the unload event could have made m_frame.document() null.
3181     if (!m_frame.document())
3182         return;
3183
3184     if (m_frame.document()->pageCacheState() != Document::NotInPageCache)
3185         return;
3186
3187     // Don't remove event listeners from a transitional empty document (see bug 28716 for more information).
3188     bool keepEventListeners = m_stateMachine.isDisplayingInitialEmptyDocument() && m_provisionalDocumentLoader
3189         && m_frame.document()->isSecureTransitionTo(m_provisionalDocumentLoader->url());
3190
3191     if (!keepEventListeners)
3192         m_frame.document()->removeAllEventListeners();
3193 }
3194
3195 static bool shouldAskForNavigationConfirmation(Document& document, const BeforeUnloadEvent& event)
3196 {
3197     // Confirmation dialog should not be displayed when the allow-modals flag is not set.
3198     if (document.isSandboxed(SandboxModals))
3199         return false;
3200
3201     bool userDidInteractWithPage = document.topDocument().userDidInteractWithPage();
3202     // Web pages can request we ask for confirmation before navigating by:
3203     // - Cancelling the BeforeUnloadEvent (modern way)
3204     // - Setting the returnValue attribute on the BeforeUnloadEvent to a non-empty string.
3205     // - Returning a non-empty string from the event handler, which is then set as returnValue
3206     //   attribute on the BeforeUnloadEvent.
3207     return userDidInteractWithPage && (event.defaultPrevented() || !event.returnValue().isEmpty());
3208 }
3209
3210 bool FrameLoader::dispatchBeforeUnloadEvent(Chrome& chrome, FrameLoader* frameLoaderBeingNavigated)
3211 {
3212     DOMWindow* domWindow = m_frame.document()->domWindow();
3213     if (!domWindow)
3214         return true;
3215
3216     RefPtr<Document> document = m_frame.document();
3217     if (!document->bodyOrFrameset())
3218         return true;
3219     
3220     Ref<BeforeUnloadEvent> beforeUnloadEvent = BeforeUnloadEvent::create();
3221     m_pageDismissalEventBeingDispatched = PageDismissalType::BeforeUnload;
3222
3223     {
3224         ForbidPromptsScope forbidPrompts(m_frame.page());
3225         domWindow->dispatchEvent(beforeUnloadEvent, domWindow->document());
3226     }
3227
3228     m_pageDismissalEventBeingDispatched = PageDismissalType::None;
3229
3230     if (!beforeUnloadEvent->defaultPrevented())
3231         document->defaultEventHandler(beforeUnloadEvent.get());
3232
3233     if (!shouldAskForNavigationConfirmation(*document, beforeUnloadEvent))
3234         return true;
3235
3236     // If the navigating FrameLoader has already shown a beforeunload confirmation panel for the current navigation attempt,
3237     // this frame is not allowed to cause another one to be shown.
3238     if (frameLoaderBeingNavigated->m_currentNavigationHasShownBeforeUnloadConfirmPanel) {
3239         document->addConsoleMessage(MessageSource::JS, MessageLevel::Error, "Blocked attempt to show multiple beforeunload confirmation dialogs for the same navigation."_s);
3240         return true;
3241     }
3242
3243     // We should only display the beforeunload dialog for an iframe if its SecurityOrigin matches all
3244     // ancestor frame SecurityOrigins up through the navigating FrameLoader.
3245     if (frameLoaderBeingNavigated != this) {
3246         Frame* parentFrame = m_frame.tree().parent();
3247         while (parentFrame) {
3248             Document* parentDocument = parentFrame->document();
3249             if (!parentDocument)
3250                 return true;
3251             if (!m_frame.document() || !m_frame.document()->securityOrigin().canAccess(parentDocument->securityOrigin())) {
3252                 document->addConsoleMessage(MessageSource::JS, MessageLevel::Error, "Blocked attempt to show beforeunload confirmation dialog on behalf of a frame with different security origin. Protocols, domains, and ports must match."_s);
3253                 return true;
3254             }
3255             
3256             if (&parentFrame->loader() == frameLoaderBeingNavigated)
3257                 break;
3258             
3259             parentFrame = parentFrame->tree().parent();
3260         }
3261         
3262         // The navigatingFrameLoader should always be in our ancestory.
3263         ASSERT(parentFrame);
3264         ASSERT(&parentFrame->loader() == frameLoaderBeingNavigated);
3265     }
3266
3267     frameLoaderBeingNavigated->m_currentNavigationHasShownBeforeUnloadConfirmPanel = true;
3268
3269     String text = document->displayStringModifiedByEncoding(beforeUnloadEvent->returnValue());
3270     return chrome.runBeforeUnloadConfirmPanel(text, m_frame);
3271 }
3272
3273 void FrameLoader::continueLoadAfterNavigationPolicy(const ResourceRequest& request, FormState* formState, ShouldContinue shouldContinue, AllowNavigationToInvalidURL allowNavigationToInvalidURL)
3274 {
3275     // If we loaded an alternate page to replace an unreachableURL, we'll get in here with a
3276     // nil policyDataSource because loading the alternate page will have passed
3277     // through this method already, nested; otherwise, policyDataSource should still be set.
3278     ASSERT(m_policyDocumentLoader || !m_provisionalDocumentLoader->unreachableURL().isEmpty());
3279
3280     bool isTargetItem = history().provisionalItem() ? history().provisionalItem()->isTargetItem() : false;
3281
3282     bool urlIsDisallowed = allowNavigationToInvalidURL == AllowNavigationToInvalidURL::No && !request.url().isValid();
3283     bool canContinue = shouldContinue != ShouldContinue::No && shouldClose() && !urlIsDisallowed;
3284
3285     if (!canContinue) {
3286         // If we were waiting for a quick redirect, but the policy delegate decided to ignore it, then we 
3287         // need to report that the client redirect was cancelled.
3288         // FIXME: The client should be told about ignored non-quick redirects, too.
3289         if (m_quickRedirectComing)
3290             clientRedirectCancelledOrFinished(false);
3291
3292         setPolicyDocumentLoader(nullptr);
3293         checkCompleted();
3294         checkLoadComplete();
3295
3296         // If the navigation request came from the back/forward menu, and we punt on it, we have the 
3297         // problem that we have optimistically moved the b/f cursor already, so move it back. For sanity,
3298         // we only do this when punting a navigation for the target frame or top-level frame.  
3299         if ((isTargetItem || m_frame.isMainFrame()) && isBackForwardLoadType(policyChecker().loadType())) {
3300             if (Page* page = m_frame.page()) {
3301                 if (HistoryItem* resetItem = m_frame.mainFrame().loader().history().currentItem()) {
3302                     page->backForward().setCurrentItem(resetItem);
3303                     m_frame.loader().client().updateGlobalHistoryItemForPage();
3304                 }
3305             }
3306         }
3307         return;
3308     }
3309
3310     FrameLoadType type = policyChecker().loadType();
3311     // A new navigation is in progress, so don't clear the history's provisional item.
3312     stopAllLoaders(ShouldNotClearProvisionalItem);
3313     
3314     // <rdar://problem/6250856> - In certain circumstances on pages with multiple frames, stopAllLoaders()
3315     // might detach the current FrameLoader, in which case we should bail on this newly defunct load. 
3316     if (!m_frame.page())
3317         return;
3318
3319     setProvisionalDocumentLoader(m_policyDocumentLoader.get());
3320     m_loadType = type;
3321     setState(FrameStateProvisional);
3322
3323     setPolicyDocumentLoader(nullptr);
3324
3325     if (isBackForwardLoadType(type)) {
3326         auto& diagnosticLoggingClient = m_frame.page()->diagnosticLoggingClient();
3327         if (history().provisionalItem()->isInPageCache()) {
3328             diagnosticLoggingClient.logDiagnosticMessageWithResult(DiagnosticLoggingKeys::pageCacheKey(), DiagnosticLoggingKeys::retrievalKey(), DiagnosticLoggingResultPass, ShouldSample::Yes);
3329             loadProvisionalItemFromCachedPage();
3330             return;
3331         }
3332         diagnosticLoggingClient.logDiagnosticMessageWithResult(DiagnosticLoggingKeys::pageCacheKey(), DiagnosticLoggingKeys::retrievalKey(), DiagnosticLoggingResultFail, ShouldSample::Yes);
3333     }
3334
3335     CompletionHandler<void()> completionHandler = [this, shouldContinue] {
3336         if (!m_provisionalDocumentLoader)
3337             return;
3338         
3339         prepareForLoadStart();
3340         
3341         // The load might be cancelled inside of prepareForLoadStart(), nulling out the m_provisionalDocumentLoader,
3342         // so we need to null check it again.
3343         if (!m_provisionalDocumentLoader) {
3344             RELEASE_LOG_IF_ALLOWED("dispatchWillSubmitForm completionHandler: Frame load canceled (frame = %p, main = %d)", &m_frame, m_frame.isMainFrame());
3345             return;
3346         }
3347         
3348         DocumentLoader* activeDocLoader = activeDocumentLoader();
3349         if (activeDocLoader && activeDocLoader->isLoadingMainResource()) {
3350             RELEASE_LOG_IF_ALLOWED("dispatchWillSubmitForm completionHandler: Main frame already being loaded (frame = %p, main = %d)", &m_frame, m_frame.isMainFrame());
3351             return;
3352         }
3353         
3354         m_loadingFromCachedPage = false;
3355
3356         // We handle suspension by navigating forward to about:blank, which leaves us setup to navigate back to resume.
3357         if (shouldContinue == ShouldContinue::ForSuspension)
3358             m_provisionalDocumentLoader->willContinueMainResourceLoadAfterRedirect({ blankURL() });
3359
3360         m_provisionalDocumentLoader->startLoadingMainResource(shouldContinue);
3361     };
3362     
3363     if (!formState) {
3364         completionHandler();
3365         return;
3366     }
3367
3368     m_client.dispatchWillSubmitForm(*formState, WTFMove(completionHandler));
3369 }
3370
3371 void FrameLoader::continueLoadAfterNewWindowPolicy(const ResourceRequest& request,
3372     FormState* formState, const String& frameName, const NavigationAction& action, ShouldContinue shouldContinue, AllowNavigationToInvalidURL allowNavigationToInvalidURL, NewFrameOpenerPolicy openerPolicy)
3373 {
3374     ASSERT(shouldContinue != ShouldContinue::ForSuspension);
3375     if (shouldContinue != ShouldContinue::Yes)
3376         return;
3377
3378     Ref<Frame> frame(m_frame);
3379     RefPtr<Frame> mainFrame = m_client.dispatchCreatePage(action);
3380     if (!mainFrame)
3381         return;
3382
3383     SandboxFlags sandboxFlags = frame->loader().effectiveSandboxFlags();
3384     if (sandboxFlags & SandboxPropagatesToAuxiliaryBrowsingContexts)
3385         mainFrame->loader().forceSandboxFlags(sandboxFlags);
3386
3387     if (!equalIgnoringASCIICase(frameName, "_blank"))
3388         mainFrame->tree().setName(frameName);
3389
3390     mainFrame->page()->setOpenedByDOM();
3391     mainFrame->loader().m_client.dispatchShow();
3392     if (openerPolicy == NewFrameOpenerPolicy::Allow) {
3393         mainFrame->loader().setOpener(frame.ptr());
3394         mainFrame->document()->setReferrerPolicy(frame->document()->referrerPolicy());
3395     }
3396
3397     NavigationAction newAction { *frame->document(), request, InitiatedByMainFrame::Unknown, NavigationType::Other, action.shouldOpenExternalURLsPolicy() };
3398     mainFrame->loader().loadWithNavigationAction(request, WTFMove(newAction), LockHistory::No, FrameLoadType::Standard, formState, allowNavigationToInvalidURL);
3399 }
3400
3401 void FrameLoader::requestFromDelegate(ResourceRequest& request, unsigned long& identifier, ResourceError& error)
3402 {
3403     ASSERT(!request.isNull());
3404
3405     identifier = 0;
3406     if (Page* page = m_frame.page()) {
3407         identifier = page->progress().createUniqueIdentifier();
3408         notifier().assignIdentifierToInitialRequest(identifier, m_documentLoader.get(), request);
3409     }
3410
3411     ResourceRequest newRequest(request);
3412     notifier().dispatchWillSendRequest(m_documentLoader.get(), identifier, newRequest, ResourceResponse());
3413
3414     if (newRequest.isNull())
3415         error = cancelledError(request);
3416     else
3417         error = ResourceError();
3418
3419     request = newRequest;
3420 }
3421
3422 void FrameLoader::loadedResourceFromMemoryCache(CachedResource& resource, ResourceRequest& newRequest, ResourceError& error)
3423 {
3424     Page* page = m_frame.page();
3425     if (!page)
3426         return;
3427
3428     if (!resource.shouldSendResourceLoadCallbacks() || m_documentLoader->haveToldClientAboutLoad(resource.url()))
3429         return;
3430
3431     // Main resource delegate messages are synthesized in MainResourceLoader, so we must not send them here.
3432     if (resource.type() == CachedResource::Type::MainResource)
3433         return;
3434
3435     if (!page->areMemoryCacheClientCallsEnabled()) {
3436         InspectorInstrumentation::didLoadResourceFromMemoryCache(*page, m_documentLoader.get(), &resource);
3437         m_documentLoader->recordMemoryCacheLoadForFutureClientNotification(resource.resourceRequest());
3438         m_documentLoader->didTellClientAboutLoad(resource.url());
3439         return;
3440     }
3441
3442     if (m_client.dispatchDidLoadResourceFromMemoryCache(m_documentLoader.get(), newRequest, resource.response(), resource.encodedSize())) {
3443         InspectorInstrumentation::didLoadResourceFromMemoryCache(*page, m_documentLoader.get(), &resource);
3444         m_documentLoader->didTellClientAboutLoad(resource.url());
3445         return;
3446     }
3447
3448     unsigned long identifier;
3449     requestFromDelegate(newRequest, identifier, error);
3450
3451     ResourceResponse response = resource.response();
3452     response.setSource(ResourceResponse::Source::MemoryCache);
3453     notifier().sendRemainingDelegateMessages(m_documentLoader.get(), identifier, newRequest, response, 0, resource.encodedSize(), 0, error);
3454 }
3455
3456 void FrameLoader::applyUserAgentIfNeeded(ResourceRequest& request)
3457 {
3458     if (!request.hasHTTPHeaderField(HTTPHeaderName::UserAgent)) {
3459         String userAgent = this->userAgent(request.url());
3460         ASSERT(!userAgent.isNull());
3461         request.setHTTPUserAgent(userAgent);
3462     }
3463 }
3464
3465 bool FrameLoader::shouldInterruptLoadForXFrameOptions(const String& content, const URL& url, unsigned long requestIdentifier)
3466 {
3467     Frame& topFrame = m_frame.tree().top();
3468     if (&m_frame == &topFrame)
3469         return false;
3470
3471     XFrameOptionsDisposition disposition = parseXFrameOptionsHeader(content);
3472
3473     switch (disposition) {
3474     case XFrameOptionsSameOrigin: {
3475         RefPtr<SecurityOrigin> origin = SecurityOrigin::create(url);
3476         if (!origin->isSameSchemeHostPort(topFrame.document()->securityOrigin()))
3477             return true;
3478         for (Frame* frame = m_frame.tree().parent(); frame; frame = frame->tree().parent()) {
3479             if (!origin->isSameSchemeHostPort(frame->document()->securityOrigin()))
3480                 return true;
3481         }
3482         return false;
3483     }
3484     case XFrameOptionsDeny:
3485         return true;
3486     case XFrameOptionsAllowAll:
3487         return false;
3488     case XFrameOptionsConflict:
3489         m_frame.document()->addConsoleMessage(MessageSource::JS, MessageLevel::Error, "Multiple 'X-Frame-Options' headers with conflicting values ('" + content + "') encountered when loading '" + url.stringCenterEllipsizedToLength() + "'. Falling back to 'DENY'.", requestIdentifier);
3490         return true;
3491     case XFrameOptionsInvalid:
3492         m_frame.document()->addConsoleMessage(MessageSource::JS, MessageLevel::Error, "Invalid 'X-Frame-Options' header encountered when loading '" + url.stringCenterEllipsizedToLength() + "': '" + content + "' is not a recognized directive. The header will be ignored.", requestIdentifier);
3493         return false;
3494     case XFrameOptionsNone:
3495         return false;
3496     }
3497     ASSERT_NOT_REACHED();
3498     return false;
3499 }
3500
3501 void FrameLoader::loadProvisionalItemFromCachedPage()
3502 {
3503     DocumentLoader* provisionalLoader = provisionalDocumentLoader();
3504     LOG(PageCache, "WebCorePageCache: Loading provisional DocumentLoader %p with URL '%s' from CachedPage", provisionalDocumentLoader(), provisionalDocumentLoader()->url().stringCenterEllipsizedToLength().utf8().data());
3505
3506     prepareForLoadStart();
3507
3508     m_loadingFromCachedPage = true;
3509
3510     // Should have timing data from previous time(s) the page was shown.
3511     ASSERT(provisionalLoader->timing().startTime());
3512     provisionalLoader->resetTiming();
3513     provisionalLoader->timing().markStartTime();
3514
3515     provisionalLoader->setCommitted(true);
3516     commitProvisionalLoad();
3517 }
3518
3519 bool FrameLoader::shouldTreatURLAsSameAsCurrent(const URL& url) const
3520 {
3521     if (!history().currentItem())
3522         return false;
3523     return url == history().currentItem()->url() || url == history().currentItem()->originalURL();
3524 }
3525
3526 bool FrameLoader::shouldTreatURLAsSrcdocDocument(const URL& url) const
3527 {
3528     if (!equalLettersIgnoringASCIICase(url.string(), "about:srcdoc"))
3529         return false;
3530     HTMLFrameOwnerElement* ownerElement = m_frame.ownerElement();
3531     if (!ownerElement)
3532         return false;
3533     if (!ownerElement->hasTagName(iframeTag))
3534         return false;
3535     return ownerElement->hasAttributeWithoutSynchronization(srcdocAttr);
3536 }
3537
3538 Frame* FrameLoader::findFrameForNavigation(const AtomicString& name, Document* activeDocument)
3539 {
3540     Frame* frame = m_frame.tree().find(name);
3541
3542     // FIXME: Eventually all callers should supply the actual activeDocument so we can call canNavigate with the right document.
3543     if (!activeDocument)
3544         activeDocument = m_frame.document();
3545
3546     if (!activeDocument->canNavigate(frame))
3547         return nullptr;
3548
3549     return frame;
3550 }
3551
3552 void FrameLoader::loadSameDocumentItem(HistoryItem& item)
3553 {
3554     ASSERT(item.documentSequenceNumber() == history().currentItem()->documentSequenceNumber());
3555
3556     Ref<Frame> protect(m_frame);
3557
3558     // Save user view state to the current history item here since we don't do a normal load.
3559     // FIXME: Does form state need to be saved here too?
3560     history().saveScrollPositionAndViewStateToItem(history().currentItem());
3561     if (FrameView* view = m_frame.view())
3562         view->setWasScrolledByUser(false);
3563
3564     history().setCurrentItem(&item);
3565         
3566     // loadInSameDocument() actually changes the URL and notifies load delegates of a "fake" load
3567     loadInSameDocument(item.url(), item.stateObject(), false);
3568
3569     // Restore user view state from the current history item here since we don't do a normal load.
3570     history().restoreScrollPositionAndViewState();
3571 }
3572
3573 // FIXME: This function should really be split into a couple pieces, some of
3574 // which should be methods of HistoryController and some of which should be
3575 // methods of FrameLoader.
3576 void FrameLoader::loadDifferentDocumentItem(HistoryItem& item, FrameLoadType loadType, FormSubmissionCacheLoadPolicy cacheLoadPolicy, ShouldTreatAsContinuingLoad shouldTreatAsContinuingLoad)
3577 {
3578     // Remember this item so we can traverse any child items as child frames load
3579     history().setProvisionalItem(&item);
3580
3581     auto initiatedByMainFrame = InitiatedByMainFrame::Unknown;
3582
3583     SetForScope<bool> currentLoadShouldBeTreatedAsContinuingLoadGuard(m_currentLoadShouldBeTreatedAsContinuingLoad, shouldTreatAsContinuingLoad == ShouldTreatAsContinuingLoad::Yes);
3584
3585     if (CachedPage* cachedPage = PageCache::singleton().get(item, m_frame.page())) {
3586         auto documentLoader = cachedPage->documentLoader();
3587         m_client.updateCachedDocumentLoader(*documentLoader);
3588
3589         auto action = NavigationAction { *m_frame.document(), documentLoader->request(), initiatedByMainFrame, loadType, false };
3590         action.setTargetBackForwardItem(item);
3591         documentLoader->setTriggeringAction(WTFMove(action));
3592
3593         documentLoader->setLastCheckedRequest(ResourceRequest());
3594         loadWithDocumentLoader(documentLoader, loadType, { }, AllowNavigationToInvalidURL::Yes, shouldTreatAsContinuingLoad);
3595         return;
3596     }
3597
3598     URL itemURL = item.url();
3599     URL itemOriginalURL = item.originalURL();
3600     URL currentURL;
3601     if (documentLoader())
3602         currentURL = documentLoader()->url();
3603     RefPtr<FormData> formData = item.formData();
3604
3605     ResourceRequest request(itemURL);
3606
3607     if (!item.referrer().isNull())
3608         request.setHTTPReferrer(item.referrer());
3609
3610     ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy = shouldOpenExternalURLsPolicyToApply(m_frame, initiatedByMainFrame, item.shouldOpenExternalURLsPolicy());
3611     bool isFormSubmission = false;
3612     Event* event = nullptr;
3613
3614     // If this was a repost that failed the page cache, we might try to repost the form.
3615     NavigationAction action;
3616     if (formData) {
3617         formData->generateFiles(m_frame.document());
3618
3619         request.setHTTPMethod("POST");
3620         request.setHTTPBody(WTFMove(formData));
3621         request.setHTTPContentType(item.formContentType());
3622         RefPtr<SecurityOrigin> securityOrigin = SecurityOrigin::createFromString(item.referrer());
3623         addHTTPOriginIfNeeded(request, securityOrigin->toString());
3624         addHTTPUpgradeInsecureRequestsIfNeeded(request);
3625
3626         // Make sure to add extra fields to the request after the Origin header is added for the FormData case.
3627         // See https://bugs.webkit.org/show_bug.cgi?id=22194 for more discussion.
3628         addExtraFieldsToRequest(request, loadType, true);
3629         
3630         // FIXME: Slight hack to test if the NSURL cache contains the page we're going to.
3631         // We want to know this before talking to the policy delegate, since it affects whether 
3632         // we show the DoYouReallyWantToRepost nag.
3633         //
3634         // This trick has a small bug (3123893) where we might find a cache hit, but then
3635         // have the item vanish when we try to use it in the ensuing nav.  This should be
3636         // extremely rare, but in that case the user will get an error on the navigation.
3637         
3638         if (cacheLoadPolicy == MayAttemptCacheOnlyLoadForFormSubmissionItem) {
3639             request.setCachePolicy(ResourceRequestCachePolicy::ReturnCacheDataDontLoad);
3640             action = { *m_frame.document(), request, initiatedByMainFrame, loadType, isFormSubmission, event, shouldOpenExternalURLsPolicy };
3641         } else {
3642             request.setCachePolicy(ResourceRequestCachePolicy::ReturnCacheDataElseLoad);
3643             action = { *m_frame.document(), request, initiatedByMainFrame, NavigationType::FormResubmitted, shouldOpenExternalURLsPolicy, event };
3644         }
3645     } else {
3646         switch (loadType) {
3647         case FrameLoadType::Reload:
3648         case FrameLoadType::ReloadFromOrigin:
3649         case FrameLoadType::ReloadExpiredOnly:
3650             request.setCachePolicy(ResourceRequestCachePolicy::ReloadIgnoringCacheData);
3651             break;
3652         case FrameLoadType::Back:
3653         case FrameLoadType::Forward:
3654         case FrameLoadType::IndexedBackForward: {
3655 #if PLATFORM(COCOA)
3656             bool allowStaleData = true;
3657 #else
3658             bool allowStaleData = !item.wasRestoredFromSession();
3659 #endif
3660             if (allowStaleData)
3661                 request.setCachePolicy(ResourceRequestCachePolicy::ReturnCacheDataElseLoad);
3662             item.setWasRestoredFromSession(false);
3663             break;
3664         }
3665         case FrameLoadType::Standard:
3666         case FrameLoadType::RedirectWithLockedBackForwardList:
3667             break;
3668         case FrameLoadType::Same:
3669         case FrameLoadType::Replace:
3670             ASSERT_NOT_REACHED();
3671         }
3672
3673         addExtraFieldsToRequest(request, loadType, true);
3674
3675         ResourceRequest requestForOriginalURL(request);
3676         requestForOriginalURL.setURL(itemOriginalURL);
3677         action = { *m_frame.document(), requestForOriginalURL, initiatedByMainFrame, loadType, isFormSubmission, event, shouldOpenExternalURLsPolicy };
3678     }
3679
3680     action.setTargetBackForwardItem(item);
3681
3682     loadWithNavigationAction(request, WTFMove(action), LockHistory::No, loadType, { }, AllowNavigationToInvalidURL::Yes);
3683 }
3684
3685 // Loads content into this frame, as specified by history item
3686 void FrameLoader::loadItem(HistoryItem& item, FrameLoadType loadType, ShouldTreatAsContinuingLoad shouldTreatAsContinuingLoad)
3687 {
3688     m_requestedHistoryItem = &item;
3689     HistoryItem* currentItem = history().currentItem();
3690     bool sameDocumentNavigation = currentItem && item.shouldDoSameDocumentNavigationTo(*currentItem);
3691
3692     if (sameDocumentNavigation)
3693         loadSameDocumentItem(item);
3694     else
3695         loadDifferentDocumentItem(item, loadType, MayAttemptCacheOnlyLoadForFormSubmissionItem, shouldTreatAsContinuingLoad);
3696 }
3697
3698 void FrameLoader::retryAfterFailedCacheOnlyMainResourceLoad()
3699 {
3700     ASSERT(m_state == FrameStateProvisional);
3701     ASSERT(!m_loadingFromCachedPage);
3702     ASSERT(history().provisionalItem());
3703     ASSERT(history().provisionalItem()->formData());
3704     ASSERT(history().provisionalItem() == m_requestedHistoryItem.get());
3705
3706     FrameLoadType loadType = m_loadType;
3707     HistoryItem& item = *history().provisionalItem();
3708
3709     stopAllLoaders(ShouldNotClearProvisionalItem);
3710     loadDifferentDocumentItem(item, loadType, MayNotAttemptCacheOnlyLoadForFormSubmissionItem, ShouldTreatAsContinuingLoad::No);
3711 }
3712
3713 ResourceError FrameLoader::cancelledError(const ResourceRequest& request) const
3714 {
3715     ResourceError error = m_client.cancelledError(request);
3716     error.setType(ResourceError::Type::Cancellation);
3717     return error;
3718 }
3719
3720 ResourceError FrameLoader::blockedByContentBlockerError(const ResourceRequest& request) const
3721 {
3722     return m_client.blockedByContentBlockerError(request);
3723 }
3724
3725 ResourceError FrameLoader::blockedError(const ResourceRequest& request) const
3726 {
3727     ResourceError error = m_client.blockedError(request);
3728     error.setType(ResourceError::Type::Cancellation);
3729     return error;
3730 }
3731
3732 #if ENABLE(CONTENT_FILTERING)
3733 ResourceError FrameLoader::blockedByContentFilterError(const ResourceRequest& request) const
3734 {
3735     ResourceError error = m_client.blockedByContentFilterError(request);
3736     error.setType(ResourceError::Type::General);
3737     return error;
3738 }
3739 #endif
3740
3741 #if PLATFORM(IOS)
3742 RetainPtr<CFDictionaryRef> FrameLoader::connectionProperties(ResourceLoader* loader)
3743 {
3744     return m_client.connectionProperties(loader->documentLoader(), loader->identifier());
3745 }
3746 #endif
3747
3748 ReferrerPolicy FrameLoader::effectiveReferrerPolicy() const
3749 {
3750     if (auto* parentFrame = m_frame.tree().parent())
3751         return parentFrame->document()->referrerPolicy();
3752     if (m_opener)
3753         return m_opener->document()->referrerPolicy();
3754     return ReferrerPolicy::NoReferrerWhenDowngrade;
3755 }
3756
3757 String FrameLoader::referrer() const
3758 {
3759     return m_documentLoader ? m_documentLoader->request().httpReferrer() : emptyString();
3760 }
3761
3762 void FrameLoader::dispatchDidClearWindowObjectsInAllWorlds()
3763 {
3764     if (!m_frame.script().canExecuteScripts(NotAboutToExecuteScript))
3765         return;
3766
3767     Vector<Ref<DOMWrapperWorld>> worlds;
3768     ScriptController::getAllWorlds(worlds);
3769     for (auto& world : worlds)
3770         dispatchDidClearWindowObjectInWorld(world);
3771 }
3772
3773 void FrameLoader::dispatchDidClearWindowObjectInWorld(DOMWrapperWorld& world)
3774 {
3775     if (!m_frame.script().canExecuteScripts(NotAboutToExecuteScript) || !m_frame.windowProxy().existingJSWindowProxy(world))
3776         return;
3777
3778     m_client.dispatchDidClearWindowObjectInWorld(world);
3779
3780     if (Page* page = m_frame.page())
3781         page->inspectorController().didClearWindowObjectInWorld(m_frame, world);
3782
3783     InspectorInstrumentation::didClearWindowObjectInWorld(m_frame, world);
3784 }
3785
3786 void FrameLoader::dispatchGlobalObjectAvailableInAllWorlds()
3787 {
3788     Vector<Ref<DOMWrapperWorld>> worlds;
3789     ScriptController::getAllWorlds(worlds);
3790     for (auto& world : worlds)
3791         m_client.dispatchGlobalObjectAvailable(world);
3792 }
3793
3794 SandboxFlags FrameLoader::effectiveSandboxFlags() const
3795 {
3796     SandboxFlags flags = m_forcedSandboxFlags;
3797     if (Frame* parentFrame = m_frame.tree().parent())
3798         flags |= parentFrame->document()->sandboxFlags();
3799     if (HTMLFrameOwnerElement* ownerElement = m_frame.ownerElement())
3800         flags |= ownerElement->sandboxFlags();
3801     return flags;
3802 }
3803
3804 void FrameLoader::didChangeTitle(DocumentLoader* loader)
3805 {
3806     m_client.didChangeTitle(loader);
3807
3808     if (loader == m_documentLoader) {
3809         // Must update the entries in the back-forward list too.
3810         history().setCurrentItemTitle(loader->title());
3811         // This must go through the WebFrame because it has the right notion of the current b/f item.
3812         m_client.setTitle(loader->title(), loader->urlForHistory());
3813         m_client.setMainFrameDocumentReady(true); // update observers with new DOMDocument
3814         m_client.dispatchDidReceiveTitle(loader->title());
3815     }
3816
3817 #if ENABLE(REMOTE_INSPECTOR)
3818     if (m_frame.isMainFrame())
3819         m_frame.page()->remoteInspectorInformationDidChange();
3820 #endif
3821 }
3822
3823 void FrameLoader::dispatchDidCommitLoad(std::optional<HasInsecureContent> initialHasInsecureContent)
3824 {
3825     if (m_stateMachine.creatingInitialEmptyDocument())
3826         return;
3827
3828     m_client.dispatchDidCommitLoad(initialHasInsecureContent);
3829
3830     if (m_frame.isMainFrame()) {
3831         m_frame.page()->resetSeenPlugins();
3832         m_frame.page()->resetSeenMediaEngines();
3833     }
3834
3835     InspectorInstrumentation::didCommitLoad(m_frame, m_documentLoader.get());
3836
3837 #if ENABLE(REMOTE_INSPECTOR)
3838     if (m_frame.isMainFrame())
3839         m_frame.page()->remoteInspectorInformationDidChange();
3840 #endif
3841 }
3842
3843 void FrameLoader::tellClientAboutPastMemoryCacheLoads()
3844 {
3845     ASSERT(m_frame.page());
3846     ASSERT(m_frame.page()->areMemoryCacheClientCallsEnabled());
3847
3848     if (!m_documentLoader)
3849         return;
3850
3851     Vector<ResourceRequest> pastLoads;
3852     m_documentLoader->takeMemoryCacheLoadsForClientNotification(pastLoads);
3853
3854     for (auto& pastLoad : pastLoads) {
3855         CachedResource* resource = MemoryCache::singleton().resourceForRequest(pastLoad, m_frame.page()->sessionID());
3856
3857         // FIXME: These loads, loaded from cache, but now gone from the cache by the time
3858         // Page::setMemoryCacheClientCallsEnabled(true) is called, will not be seen by the client.
3859         // Consider if there's some efficient way of remembering enough to deliver this client call.
3860         // We have the URL, but not the rest of the response or the length.
3861         if (!resource)
3862             continue;
3863
3864         ResourceRequest request(resource->url());
3865         m_client.dispatchDidLoadResourceFromMemoryCache(m_documentLoader.get(), request, resource->response(), resource->encodedSize());
3866     }
3867 }
3868
3869 NetworkingContext* FrameLoader::networkingContext() const
3870 {
3871     return m_networkingContext.get();
3872 }
3873
3874 void FrameLoader::loadProgressingStatusChanged()
3875 {
3876     if (auto* view = m_frame.mainFrame().view())
3877         view->loadProgressingStatusChanged();
3878 }
3879
3880 void FrameLoader::forcePageTransitionIfNeeded()
3881 {
3882     m_client.forcePageTransitionIfNeeded();
3883 }
3884
3885 void FrameLoader::clearTestingOverrides()
3886 {
3887     m_overrideCachePolicyForTesting = std::nullopt;
3888     m_overrideResourceLoadPriorityForTesting = std::nullopt;
3889     m_isStrictRawResourceValidationPolicyDisabledForTesting = false;
3890 }
3891
3892 bool FrameLoader::isAlwaysOnLoggingAllowed() const
3893 {
3894     return frame().isAlwaysOnLoggingAllowed();
3895 }
3896
3897 bool FrameLoaderClient::hasHTMLView() const
3898 {
3899     return true;
3900 }
3901
3902 RefPtr<Frame> createWindow(Frame& openerFrame, Frame& lookupFrame, FrameLoadRequest&& request, const WindowFeatures& features, bool& created)
3903 {
3904     ASSERT(!features.dialog || request.frameName().isEmpty());
3905
3906     created = false;
3907
3908     // FIXME: Provide line number information with respect to the opener's document.
3909     if (protocolIsJavaScript(request.resourceRequest().url()) && !openerFrame.document()->contentSecurityPolicy()->allowJavaScriptURLs(openerFrame.document()->url(), { }))
3910         return nullptr;
3911
3912     if (!request.frameName().isEmpty() && !equalIgnoringASCIICase(request.frameName(), "_blank")) {
3913         if (RefPtr<Frame> frame = lookupFrame.loader().findFrameForNavigation(request.frameName(), openerFrame.document())) {
3914             if (!equalIgnoringASCIICase(request.frameName(), "_self")) {
3915                 if (Page* page = frame->page())
3916                     page->chrome().focus();
3917             }
3918             return frame;
3919         }
3920     }
3921
3922     // Sandboxed frames cannot open new auxiliary browsing contexts.
3923     if (isDocumentSandboxed(openerFrame, SandboxPopups)) {
3924         // FIXME: This message should be moved off the console once a solution to https://bugs.webkit.org/show_bug.cgi?id=103274 exists.
3925         openerFrame.document()->addConsoleMessage(MessageSource::Security, MessageLevel::Error, "Blocked opening '" + request.resourceRequest().url().stringCenterEllipsizedToLength() + "' in a new window because the request was made in a sandboxed frame whose 'allow-popups' permission is not set.");
3926         return nullptr;
3927     }
3928
3929     // FIXME: Setting the referrer should be the caller's responsibility.
3930     String referrer = SecurityPolicy::generateReferrerHeader(openerFrame.document()->referrerPolicy(), request.resourceRequest().url(), openerFrame.loader().outgoingReferrer());
3931     if (!referrer.isEmpty())
3932         request.resourceRequest().setHTTPReferrer(referrer);
3933     FrameLoader::addHTTPOriginIfNeeded(request.resourceRequest(), openerFrame.loader().outgoingOrigin());
3934     FrameLoader::addHTTPUpgradeInsecureRequestsIfNeeded(request.resourceRequest());
3935     FrameLoader::addSameSiteInfoToRequestIfNeeded(request.resourceRequest(), openerFrame.document());
3936
3937     Page* oldPage = openerFrame.page();
3938     if (!oldPage)
3939         return nullptr;
3940
3941     ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy = shouldOpenExternalURLsPolicyToApply(openerFrame, request);
3942     NavigationAction action { request.requester(), request.resourceRequest(), request.initiatedByMainFrame(), NavigationType::Other, shouldOpenExternalURLsPolicy };
3943     Page* page = oldPage->chrome().createWindow(openerFrame, request, features, action);
3944     if (!page)
3945         return nullptr;
3946
3947     RefPtr<Frame> frame = &page->mainFrame();
3948
3949     if (isDocumentSandboxed(openerFrame, SandboxPropagatesToAuxiliaryBrowsingContexts))
3950         frame->loader().forceSandboxFlags(openerFrame.document()->sandboxFlags());
3951
3952     if (!equalIgnoringASCIICase(request.frameName(), "_blank"))
3953         frame->tree().setName(request.frameName());
3954
3955     page->chrome().setToolbarsVisible(features.toolBarVisible || features.locationBarVisible);
3956
3957     if (!frame->page())
3958         return nullptr;
3959     page->chrome().setStatusbarVisible(features.statusBarVisible);
3960
3961     if (!frame->page())
3962         return nullptr;
3963     page->chrome().setScrollbarsVisible(features.scrollbarsVisible);
3964
3965     if (!frame->page())
3966         return nullptr;
3967     page->chrome().setMenubarVisible(features.menuBarVisible);
3968
3969     if (!frame->page())
3970         return nullptr;
3971     page->chrome().setResizable(features.resizable);
3972
3973     // 'x' and 'y' specify the location of the window, while 'width' and 'height'
3974     // specify the size of the viewport. We can only resize the window, so adjust
3975     // for the difference between the window size and the viewport size.
3976
3977     // FIXME: We should reconcile the initialization of viewport arguments between iOS and non-IOS.
3978 #if !PLATFORM(IOS)
3979     FloatSize viewportSize = page->chrome().pageRect().size();
3980     FloatRect windowRect = page->chrome().windowRect();
3981     if (features.x)
3982         windowRect.setX(*features.x);
3983     if (features.y)
3984         windowRect.setY(*features.y);
3985     // Zero width and height mean using default size, not minumum one.