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