Implement Same-Site cookies
[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     String registrableDomain = ResourceRequest::partitionName(url.host());
1060     for (Frame* frame = &m_frame; frame; frame = frame->tree().traverseNext(&m_frame)) {
1061         if (SecurityPolicy::shouldInheritSecurityOriginFromOwner(frame->document()->url()) || registrableDomainsAreEqual(frame->document()->url(), registrableDomain))
1062             frame->document()->setFirstPartyForSameSiteCookies(url);
1063     }
1064 }
1065
1066 // This does the same kind of work that didOpenURL does, except it relies on the fact
1067 // that a higher level already checked that the URLs match and the scrolling is the right thing to do.
1068 void FrameLoader::loadInSameDocument(const URL& url, SerializedScriptValue* stateObject, bool isNewNavigation)
1069 {
1070     // If we have a state object, we cannot also be a new navigation.
1071     ASSERT(!stateObject || (stateObject && !isNewNavigation));
1072
1073     // Update the data source's request with the new URL to fake the URL change
1074     URL oldURL = m_frame.document()->url();
1075     m_frame.document()->setURL(url);
1076     setOutgoingReferrer(url);
1077     documentLoader()->replaceRequestURLForSameDocumentNavigation(url);
1078     if (isNewNavigation && !shouldTreatURLAsSameAsCurrent(url) && !stateObject) {
1079         // NB: must happen after replaceRequestURLForSameDocumentNavigation(), since we add 
1080         // based on the current request. Must also happen before we openURL and displace the 
1081         // scroll position, since adding the BF item will save away scroll state.
1082         
1083         // NB2: If we were loading a long, slow doc, and the user fragment navigated before
1084         // it was done, currItem is now set the that slow doc, and prevItem is whatever was
1085         // before it.  Adding the b/f item will bump the slow doc down to prevItem, even
1086         // though its load is not yet done.  I think this all works out OK, for one because
1087         // we have already saved away the scroll and doc state for the long slow load,
1088         // but it's not an obvious case.
1089
1090         history().updateBackForwardListForFragmentScroll();
1091     }
1092     
1093     bool hashChange = equalIgnoringFragmentIdentifier(url, oldURL) && url.fragmentIdentifier() != oldURL.fragmentIdentifier();
1094     
1095     history().updateForSameDocumentNavigation();
1096
1097     // If we were in the autoscroll/panScroll mode we want to stop it before following the link to the anchor
1098     if (hashChange)
1099         m_frame.eventHandler().stopAutoscrollTimer();
1100     
1101     // It's important to model this as a load that starts and immediately finishes.
1102     // Otherwise, the parent frame may think we never finished loading.
1103     started();
1104
1105     // We need to scroll to the fragment whether or not a hash change occurred, since
1106     // the user might have scrolled since the previous navigation.
1107     scrollToFragmentWithParentBoundary(url, isNewNavigation);
1108     
1109     m_isComplete = false;
1110     checkCompleted();
1111
1112     if (isNewNavigation) {
1113         // This will clear previousItem from the rest of the frame tree that didn't
1114         // doing any loading. We need to make a pass on this now, since for fragment
1115         // navigation we'll not go through a real load and reach Completed state.
1116         checkLoadComplete();
1117     }
1118
1119     m_client.dispatchDidNavigateWithinPage();
1120
1121     m_frame.document()->statePopped(stateObject ? Ref<SerializedScriptValue> { *stateObject } : SerializedScriptValue::nullValue());
1122     m_client.dispatchDidPopStateWithinPage();
1123     
1124     if (hashChange) {
1125         m_frame.document()->enqueueHashchangeEvent(oldURL, url);
1126         m_client.dispatchDidChangeLocationWithinPage();
1127     }
1128     
1129     // FrameLoaderClient::didFinishLoad() tells the internal load delegate the load finished with no error
1130     m_client.didFinishLoad();
1131 }
1132
1133 bool FrameLoader::isComplete() const
1134 {
1135     return m_isComplete;
1136 }
1137
1138 void FrameLoader::completed()
1139 {
1140     Ref<Frame> protect(m_frame);
1141
1142     for (Frame* descendant = m_frame.tree().traverseNext(&m_frame); descendant; descendant = descendant->tree().traverseNext(&m_frame))
1143         descendant->navigationScheduler().startTimer();
1144
1145     if (Frame* parent = m_frame.tree().parent())
1146         parent->loader().checkCompleted();
1147
1148     if (m_frame.view())
1149         m_frame.view()->maintainScrollPositionAtAnchor(nullptr);
1150 }
1151
1152 void FrameLoader::started()
1153 {
1154     for (Frame* frame = &m_frame; frame; frame = frame->tree().parent())
1155         frame->loader().m_isComplete = false;
1156 }
1157
1158 void FrameLoader::prepareForLoadStart()
1159 {
1160     RELEASE_LOG_IF_ALLOWED("prepareForLoadStart: Starting frame load (frame = %p, main = %d)", &m_frame, m_frame.isMainFrame());
1161
1162     m_progressTracker->progressStarted();
1163     m_client.dispatchDidStartProvisionalLoad();
1164
1165     if (AXObjectCache::accessibilityEnabled()) {
1166         if (AXObjectCache* cache = m_frame.document()->existingAXObjectCache()) {
1167             AXObjectCache::AXLoadingEvent loadingEvent = loadType() == FrameLoadType::Reload ? AXObjectCache::AXLoadingReloaded : AXObjectCache::AXLoadingStarted;
1168             cache->frameLoadingEventNotification(&m_frame, loadingEvent);
1169         }
1170     }
1171 }
1172
1173 void FrameLoader::setupForReplace()
1174 {
1175     m_client.revertToProvisionalState(m_documentLoader.get());
1176     setState(FrameStateProvisional);
1177     m_provisionalDocumentLoader = m_documentLoader;
1178     m_documentLoader = nullptr;
1179     detachChildren();
1180 }
1181
1182 void FrameLoader::loadFrameRequest(FrameLoadRequest&& request, Event* event, FormState* formState)
1183 {
1184     // Protect frame from getting blown away inside dispatchBeforeLoadEvent in loadWithDocumentLoader.
1185     auto protectFrame = makeRef(m_frame);
1186
1187     URL url = request.resourceRequest().url();
1188
1189     ASSERT(m_frame.document());
1190     if (!request.requesterSecurityOrigin().canDisplay(url)) {
1191         reportLocalLoadFailed(&m_frame, url.stringCenterEllipsizedToLength());
1192         return;
1193     }
1194
1195     String argsReferrer = request.resourceRequest().httpReferrer();
1196     if (argsReferrer.isEmpty())
1197         argsReferrer = outgoingReferrer();
1198
1199     String referrer = SecurityPolicy::generateReferrerHeader(m_frame.document()->referrerPolicy(), url, argsReferrer);
1200     if (request.shouldSendReferrer() == NeverSendReferrer)
1201         referrer = String();
1202
1203     FrameLoadType loadType;
1204     if (request.resourceRequest().cachePolicy() == ReloadIgnoringCacheData)
1205         loadType = FrameLoadType::Reload;
1206     else if (request.lockBackForwardList() == LockBackForwardList::Yes)
1207         loadType = FrameLoadType::RedirectWithLockedBackForwardList;
1208     else
1209         loadType = FrameLoadType::Standard;
1210
1211     auto completionHandler = [this, protectedFrame = makeRef(m_frame), formState = makeRefPtr(formState), frameName = request.frameName()] {
1212         // FIXME: It's possible this targetFrame will not be the same frame that was targeted by the actual
1213         // load if frame names have changed.
1214         Frame* sourceFrame = formState ? formState->sourceDocument().frame() : &m_frame;
1215         if (!sourceFrame)
1216             sourceFrame = &m_frame;
1217         Frame* targetFrame = sourceFrame->loader().findFrameForNavigation(frameName);
1218         if (targetFrame && targetFrame != sourceFrame) {
1219             if (Page* page = targetFrame->page())
1220                 page->chrome().focus();
1221         }
1222     };
1223
1224     if (request.resourceRequest().httpMethod() == "POST")
1225         loadPostRequest(WTFMove(request), referrer, loadType, event, formState, WTFMove(completionHandler));
1226     else
1227         loadURL(WTFMove(request), referrer, loadType, event, formState, WTFMove(completionHandler));
1228 }
1229
1230 static ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicyToApply(Frame& currentFrame, InitiatedByMainFrame initiatedByMainFrame, ShouldOpenExternalURLsPolicy propagatedPolicy)
1231 {
1232     if (UserGestureIndicator::processingUserGesture())
1233         return ShouldOpenExternalURLsPolicy::ShouldAllow;
1234
1235     if (initiatedByMainFrame == InitiatedByMainFrame::Yes)
1236         return propagatedPolicy;
1237
1238     if (!currentFrame.isMainFrame())
1239         return ShouldOpenExternalURLsPolicy::ShouldNotAllow;
1240
1241     return propagatedPolicy;
1242 }
1243
1244 static ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicyToApply(Frame& currentFrame, const FrameLoadRequest& frameLoadRequest)
1245 {
1246     return shouldOpenExternalURLsPolicyToApply(currentFrame, frameLoadRequest.initiatedByMainFrame(), frameLoadRequest.shouldOpenExternalURLsPolicy());
1247 }
1248
1249 static void applyShouldOpenExternalURLsPolicyToNewDocumentLoader(Frame& frame, DocumentLoader& documentLoader, InitiatedByMainFrame initiatedByMainFrame, ShouldOpenExternalURLsPolicy propagatedPolicy)
1250 {
1251     documentLoader.setShouldOpenExternalURLsPolicy(shouldOpenExternalURLsPolicyToApply(frame, initiatedByMainFrame, propagatedPolicy));
1252 }
1253
1254 static void applyShouldOpenExternalURLsPolicyToNewDocumentLoader(Frame& frame, DocumentLoader& documentLoader, const FrameLoadRequest& frameLoadRequest)
1255 {
1256     documentLoader.setShouldOpenExternalURLsPolicy(shouldOpenExternalURLsPolicyToApply(frame, frameLoadRequest));
1257 }
1258
1259 bool FrameLoader::isNavigationAllowed() const
1260 {
1261     return m_pageDismissalEventBeingDispatched == PageDismissalType::None && NavigationDisabler::isNavigationAllowed(m_frame);
1262 }
1263
1264 bool FrameLoader::isStopLoadingAllowed() const
1265 {
1266     return m_pageDismissalEventBeingDispatched == PageDismissalType::None;
1267 }
1268
1269 void FrameLoader::loadURL(FrameLoadRequest&& frameLoadRequest, const String& referrer, FrameLoadType newLoadType, Event* event, FormState* formState, CompletionHandler<void()>&& completionHandler)
1270 {
1271     CompletionHandlerCallingScope completionHandlerCaller(WTFMove(completionHandler));
1272     if (m_inStopAllLoaders)
1273         return;
1274
1275     Ref<Frame> protect(m_frame);
1276
1277     String frameName = frameLoadRequest.frameName();
1278     AllowNavigationToInvalidURL allowNavigationToInvalidURL = frameLoadRequest.allowNavigationToInvalidURL();
1279     NewFrameOpenerPolicy openerPolicy = frameLoadRequest.newFrameOpenerPolicy();
1280     LockHistory lockHistory = frameLoadRequest.lockHistory();
1281     bool isFormSubmission = formState;
1282
1283     const URL& newURL = frameLoadRequest.resourceRequest().url();
1284     ResourceRequest request(newURL);
1285     if (!referrer.isEmpty()) {
1286         request.setHTTPReferrer(referrer);
1287         RefPtr<SecurityOrigin> referrerOrigin = SecurityOrigin::createFromString(referrer);
1288         addHTTPOriginIfNeeded(request, referrerOrigin->toString());
1289     }
1290     if (&m_frame.tree().top() != &m_frame)
1291         request.setDomainForCachePartition(m_frame.tree().top().document()->domainForCachePartition());
1292
1293     addExtraFieldsToRequest(request, newLoadType, true);
1294     if (isReload(newLoadType))
1295         request.setCachePolicy(ReloadIgnoringCacheData);
1296
1297     ASSERT(newLoadType != FrameLoadType::Same);
1298
1299     // The search for a target frame is done earlier in the case of form submission.
1300     Frame* targetFrame = isFormSubmission ? nullptr : findFrameForNavigation(frameName);
1301     if (targetFrame && targetFrame != &m_frame) {
1302         frameLoadRequest.setFrameName("_self");
1303         targetFrame->loader().loadURL(WTFMove(frameLoadRequest), referrer, newLoadType, event, formState, completionHandlerCaller.release());
1304         return;
1305     }
1306
1307     if (!isNavigationAllowed())
1308         return;
1309
1310     NavigationAction action { frameLoadRequest.requester(), request, frameLoadRequest.initiatedByMainFrame(), newLoadType, isFormSubmission, event, frameLoadRequest.shouldOpenExternalURLsPolicy(), frameLoadRequest.downloadAttribute() };
1311     action.setIsCrossOriginWindowOpenNavigation(frameLoadRequest.isCrossOriginWindowOpenNavigation());
1312     if (auto* opener = this->opener()) {
1313         auto pageID = opener->loader().client().pageID();
1314         auto frameID = opener->loader().client().frameID();
1315         if (pageID && frameID)
1316             action.setOpener(std::make_pair(*pageID, *frameID));
1317     }
1318
1319     if (!targetFrame && !frameName.isEmpty()) {
1320         action = action.copyWithShouldOpenExternalURLsPolicy(shouldOpenExternalURLsPolicyToApply(m_frame, frameLoadRequest));
1321         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) {
1322             continueLoadAfterNewWindowPolicy(request, formState, frameName, action, shouldContinue, allowNavigationToInvalidURL, openerPolicy);
1323             completionHandler();
1324         });
1325         return;
1326     }
1327
1328     RefPtr<DocumentLoader> oldDocumentLoader = m_documentLoader;
1329
1330     bool sameURL = shouldTreatURLAsSameAsCurrent(newURL);
1331     const String& httpMethod = request.httpMethod();
1332     
1333     // Make sure to do scroll to fragment processing even if the URL is
1334     // exactly the same so pages with '#' links and DHTML side effects
1335     // work properly.
1336     if (shouldPerformFragmentNavigation(isFormSubmission, httpMethod, newLoadType, newURL)) {
1337         oldDocumentLoader->setTriggeringAction(action);
1338         oldDocumentLoader->setLastCheckedRequest(ResourceRequest());
1339         policyChecker().stopCheck();
1340         policyChecker().setLoadType(newLoadType);
1341         policyChecker().checkNavigationPolicy(ResourceRequest(request), false /* didReceiveRedirectResponse */, oldDocumentLoader.get(), formState, [this, protectedFrame = makeRef(m_frame)] (const ResourceRequest& request, FormState*, ShouldContinue shouldContinue) {
1342             continueFragmentScrollAfterNavigationPolicy(request, shouldContinue == ShouldContinue::Yes);
1343         }, PolicyDecisionMode::Synchronous);
1344         return;
1345     }
1346
1347     // must grab this now, since this load may stop the previous load and clear this flag
1348     bool isRedirect = m_quickRedirectComing;
1349     loadWithNavigationAction(request, action, lockHistory, newLoadType, formState, allowNavigationToInvalidURL, [this, isRedirect, sameURL, newLoadType, protectedFrame = makeRef(m_frame), completionHandler = completionHandlerCaller.release()] {
1350         if (isRedirect) {
1351             m_quickRedirectComing = false;
1352             if (m_provisionalDocumentLoader)
1353                 m_provisionalDocumentLoader->setIsClientRedirect(true);
1354             else if (m_policyDocumentLoader)
1355                 m_policyDocumentLoader->setIsClientRedirect(true);
1356         } else if (sameURL && !isReload(newLoadType)) {
1357             // Example of this case are sites that reload the same URL with a different cookie
1358             // driving the generated content, or a master frame with links that drive a target
1359             // frame, where the user has clicked on the same link repeatedly.
1360             m_loadType = FrameLoadType::Same;
1361         }
1362         completionHandler();
1363     });
1364 }
1365
1366 SubstituteData FrameLoader::defaultSubstituteDataForURL(const URL& url)
1367 {
1368     if (!shouldTreatURLAsSrcdocDocument(url))
1369         return SubstituteData();
1370     auto& srcdoc = m_frame.ownerElement()->attributeWithoutSynchronization(srcdocAttr);
1371     ASSERT(!srcdoc.isNull());
1372     CString encodedSrcdoc = srcdoc.string().utf8();
1373
1374     ResourceResponse response(URL(), ASCIILiteral("text/html"), encodedSrcdoc.length(), ASCIILiteral("UTF-8"));
1375     return SubstituteData(SharedBuffer::create(encodedSrcdoc.data(), encodedSrcdoc.length()), URL(), response, SubstituteData::SessionHistoryVisibility::Hidden);
1376 }
1377
1378 void FrameLoader::load(FrameLoadRequest&& request)
1379 {
1380     if (m_inStopAllLoaders)
1381         return;
1382
1383     if (!request.frameName().isEmpty()) {
1384         Frame* frame = findFrameForNavigation(request.frameName());
1385         if (frame) {
1386             request.setShouldCheckNewWindowPolicy(false);
1387             if (&frame->loader() != this) {
1388                 frame->loader().load(WTFMove(request));
1389                 return;
1390             }
1391         }
1392     }
1393
1394     if (request.shouldCheckNewWindowPolicy()) {
1395         NavigationAction action { request.requester(), request.resourceRequest(), InitiatedByMainFrame::Unknown, NavigationType::Other, request.shouldOpenExternalURLsPolicy() };
1396         policyChecker().checkNewWindowPolicy(WTFMove(action), request.resourceRequest(), nullptr, request.frameName(), [this] (const ResourceRequest& request, FormState* formState, const String& frameName, const NavigationAction& action, ShouldContinue shouldContinue) {
1397             continueLoadAfterNewWindowPolicy(request, formState, frameName, action, shouldContinue, AllowNavigationToInvalidURL::Yes, NewFrameOpenerPolicy::Suppress);
1398         });
1399
1400         return;
1401     }
1402
1403     if (!request.hasSubstituteData())
1404         request.setSubstituteData(defaultSubstituteDataForURL(request.resourceRequest().url()));
1405
1406     Ref<DocumentLoader> loader = m_client.createDocumentLoader(request.resourceRequest(), request.substituteData());
1407     addSameSiteInfoToRequestIfNeeded(loader->request());
1408     applyShouldOpenExternalURLsPolicyToNewDocumentLoader(m_frame, loader, request);
1409
1410     SetForScope<bool> currentLoadShouldCheckNavigationPolicyGuard(m_currentLoadShouldCheckNavigationPolicy, request.shouldCheckNavigationPolicy());
1411     load(loader.ptr());
1412 }
1413
1414 void FrameLoader::loadWithNavigationAction(const ResourceRequest& request, const NavigationAction& action, LockHistory lockHistory, FrameLoadType type, FormState* formState, AllowNavigationToInvalidURL allowNavigationToInvalidURL, CompletionHandler<void()>&& completionHandler)
1415 {
1416     Ref<DocumentLoader> loader = m_client.createDocumentLoader(request, defaultSubstituteDataForURL(request.url()));
1417     applyShouldOpenExternalURLsPolicyToNewDocumentLoader(m_frame, loader, action.initiatedByMainFrame(), action.shouldOpenExternalURLsPolicy());
1418
1419     if (lockHistory == LockHistory::Yes && m_documentLoader)
1420         loader->setClientRedirectSourceForHistory(m_documentLoader->didCreateGlobalHistoryEntry() ? m_documentLoader->urlForHistory().string() : m_documentLoader->clientRedirectSourceForHistory());
1421
1422     loader->setTriggeringAction(action);
1423     if (m_documentLoader)
1424         loader->setOverrideEncoding(m_documentLoader->overrideEncoding());
1425
1426     loadWithDocumentLoader(loader.ptr(), type, formState, allowNavigationToInvalidURL, NavigationPolicyCheck::Require, WTFMove(completionHandler));
1427 }
1428
1429 void FrameLoader::load(DocumentLoader* newDocumentLoader)
1430 {
1431     ResourceRequest& r = newDocumentLoader->request();
1432     addExtraFieldsToMainResourceRequest(r);
1433     FrameLoadType type;
1434
1435     if (shouldTreatURLAsSameAsCurrent(newDocumentLoader->originalRequest().url())) {
1436         r.setCachePolicy(ReloadIgnoringCacheData);
1437         type = FrameLoadType::Same;
1438     } else if (shouldTreatURLAsSameAsCurrent(newDocumentLoader->unreachableURL()) && isReload(m_loadType))
1439         type = m_loadType;
1440     else if (m_loadType == FrameLoadType::RedirectWithLockedBackForwardList && !newDocumentLoader->unreachableURL().isEmpty() && newDocumentLoader->substituteData().isValid())
1441         type = FrameLoadType::RedirectWithLockedBackForwardList;
1442     else
1443         type = FrameLoadType::Standard;
1444
1445     if (m_documentLoader)
1446         newDocumentLoader->setOverrideEncoding(m_documentLoader->overrideEncoding());
1447     
1448     // When we loading alternate content for an unreachable URL that we're
1449     // visiting in the history list, we treat it as a reload so the history list 
1450     // is appropriately maintained.
1451     //
1452     // FIXME: This seems like a dangerous overloading of the meaning of "FrameLoadType::Reload" ...
1453     // shouldn't a more explicit type of reload be defined, that means roughly 
1454     // "load without affecting history" ? 
1455     if (shouldReloadToHandleUnreachableURL(newDocumentLoader)) {
1456         // shouldReloadToHandleUnreachableURL() returns true only when the original load type is back-forward.
1457         // In this case we should save the document state now. Otherwise the state can be lost because load type is
1458         // changed and updateForBackForwardNavigation() will not be called when loading is committed.
1459         history().saveDocumentAndScrollState();
1460
1461         ASSERT(type == FrameLoadType::Standard);
1462         type = FrameLoadType::Reload;
1463     }
1464
1465     loadWithDocumentLoader(newDocumentLoader, type, 0, AllowNavigationToInvalidURL::Yes, NavigationPolicyCheck::Require, [] { });
1466 }
1467
1468 void FrameLoader::loadWithDocumentLoader(DocumentLoader* loader, FrameLoadType type, FormState* formState, AllowNavigationToInvalidURL allowNavigationToInvalidURL, NavigationPolicyCheck, CompletionHandler<void()>&& completionHandler)
1469 {
1470     // Retain because dispatchBeforeLoadEvent may release the last reference to it.
1471     Ref<Frame> protect(m_frame);
1472
1473     CompletionHandlerCallingScope completionHandlerCaller(WTFMove(completionHandler));
1474
1475     ASSERT(m_client.hasWebView());
1476
1477     // Unfortunately the view must be non-nil, this is ultimately due
1478     // to parser requiring a FrameView.  We should fix this dependency.
1479
1480     ASSERT(m_frame.view());
1481
1482     if (!isNavigationAllowed())
1483         return;
1484
1485     if (m_frame.document())
1486         m_previousURL = m_frame.document()->url();
1487
1488     const URL& newURL = loader->request().url();
1489
1490     // Log main frame navigation types.
1491     if (m_frame.isMainFrame()) {
1492         if (auto* page = m_frame.page()) {
1493             page->mainFrameLoadStarted(newURL, type);
1494             page->performanceLogging().didReachPointOfInterest(PerformanceLogging::MainFrameLoadStarted);
1495         }
1496     }
1497
1498     policyChecker().setLoadType(type);
1499     bool isFormSubmission = formState;
1500
1501     const String& httpMethod = loader->request().httpMethod();
1502
1503     if (shouldPerformFragmentNavigation(isFormSubmission, httpMethod, policyChecker().loadType(), newURL)) {
1504         RefPtr<DocumentLoader> oldDocumentLoader = m_documentLoader;
1505         NavigationAction action { *m_frame.document(), loader->request(), InitiatedByMainFrame::Unknown, policyChecker().loadType(), isFormSubmission };
1506
1507         oldDocumentLoader->setTriggeringAction(action);
1508         oldDocumentLoader->setLastCheckedRequest(ResourceRequest());
1509         policyChecker().stopCheck();
1510         policyChecker().checkNavigationPolicy(ResourceRequest(loader->request()), false /* didReceiveRedirectResponse */, oldDocumentLoader.get(), formState, [this, protectedFrame = makeRef(m_frame)] (const ResourceRequest& request, FormState*, ShouldContinue shouldContinue) {
1511             continueFragmentScrollAfterNavigationPolicy(request, shouldContinue == ShouldContinue::Yes);
1512         }, PolicyDecisionMode::Synchronous);
1513         return;
1514     }
1515
1516     if (Frame* parent = m_frame.tree().parent())
1517         loader->setOverrideEncoding(parent->loader().documentLoader()->overrideEncoding());
1518
1519     policyChecker().stopCheck();
1520     setPolicyDocumentLoader(loader);
1521     if (loader->triggeringAction().isEmpty())
1522         loader->setTriggeringAction({ *m_frame.document(), loader->request(), InitiatedByMainFrame::Unknown, policyChecker().loadType(), isFormSubmission });
1523
1524     if (Element* ownerElement = m_frame.ownerElement()) {
1525         // We skip dispatching the beforeload event if we've already
1526         // committed a real document load because the event would leak
1527         // subsequent activity by the frame which the parent frame isn't
1528         // supposed to learn. For example, if the child frame navigated to
1529         // a new URL, the parent frame shouldn't learn the URL.
1530         if (!m_stateMachine.committedFirstRealDocumentLoad()
1531             && !ownerElement->dispatchBeforeLoadEvent(loader->request().url().string())) {
1532             continueLoadAfterNavigationPolicy(loader->request(), formState, ShouldContinue::No, allowNavigationToInvalidURL);
1533             return;
1534         }
1535     }
1536
1537     m_frame.navigationScheduler().cancel(true);
1538
1539     if (!m_currentLoadShouldCheckNavigationPolicy) {
1540         continueLoadAfterNavigationPolicy(loader->request(), formState, ShouldContinue::Yes, allowNavigationToInvalidURL);
1541         return;
1542     }
1543
1544     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) {
1545         continueLoadAfterNavigationPolicy(request, formState, shouldContinue, allowNavigationToInvalidURL);
1546         completionHandler();
1547     });
1548 }
1549
1550 void FrameLoader::clearProvisionalLoadForPolicyCheck()
1551 {
1552     if (!m_policyDocumentLoader || !m_provisionalDocumentLoader)
1553         return;
1554
1555     m_provisionalDocumentLoader->stopLoading();
1556     setProvisionalDocumentLoader(nullptr);
1557 }
1558
1559 void FrameLoader::reportLocalLoadFailed(Frame* frame, const String& url)
1560 {
1561     ASSERT(!url.isEmpty());
1562     if (!frame)
1563         return;
1564
1565     frame->document()->addConsoleMessage(MessageSource::Security, MessageLevel::Error, "Not allowed to load local resource: " + url);
1566 }
1567
1568 void FrameLoader::reportBlockedPortFailed(Frame* frame, const String& url)
1569 {
1570     ASSERT(!url.isEmpty());
1571     if (!frame)
1572         return;
1573     
1574     frame->document()->addConsoleMessage(MessageSource::Security, MessageLevel::Error, "Not allowed to use restricted network port: " + url);
1575 }
1576
1577 void FrameLoader::reportAuthenticationChallengeBlocked(Frame* frame, const URL& url, const String& reason)
1578 {
1579     if (!frame)
1580         return;
1581
1582     frame->document()->addConsoleMessage(MessageSource::Security, MessageLevel::Error, makeString("Blocked ", url.stringCenterEllipsizedToLength(), " from asking for credentials because ", reason, '.'));
1583 }
1584
1585 const ResourceRequest& FrameLoader::initialRequest() const
1586 {
1587     return activeDocumentLoader()->originalRequest();
1588 }
1589
1590 bool FrameLoader::willLoadMediaElementURL(URL& url)
1591 {
1592 #if PLATFORM(IOS)
1593     // MobileStore depends on the iOS 4.0 era client delegate method because webView:resource:willSendRequest:redirectResponse:fromDataSource
1594     // doesn't let them tell when a load request is coming from a media element. See <rdar://problem/8266916> for more details.
1595     if (IOSApplication::isMobileStore())
1596         return m_client.shouldLoadMediaElementURL(url);
1597 #endif
1598
1599     ResourceRequest request(url);
1600
1601     unsigned long identifier;
1602     ResourceError error;
1603     requestFromDelegate(request, identifier, error);
1604     notifier().sendRemainingDelegateMessages(m_documentLoader.get(), identifier, request, ResourceResponse(url, String(), -1, String()), 0, -1, -1, error);
1605
1606     url = request.url();
1607
1608     return error.isNull();
1609 }
1610
1611 bool FrameLoader::shouldReloadToHandleUnreachableURL(DocumentLoader* docLoader)
1612 {
1613     URL unreachableURL = docLoader->unreachableURL();
1614
1615     if (unreachableURL.isEmpty())
1616         return false;
1617
1618     if (!isBackForwardLoadType(policyChecker().loadType()))
1619         return false;
1620
1621     // We only treat unreachableURLs specially during the delegate callbacks
1622     // for provisional load errors and navigation policy decisions. The former
1623     // case handles well-formed URLs that can't be loaded, and the latter
1624     // case handles malformed URLs and unknown schemes. Loading alternate content
1625     // at other times behaves like a standard load.
1626     if (policyChecker().delegateIsDecidingNavigationPolicy() || policyChecker().delegateIsHandlingUnimplementablePolicy())
1627         return m_policyDocumentLoader && unreachableURL == m_policyDocumentLoader->request().url();
1628
1629     return unreachableURL == m_provisionalLoadErrorBeingHandledURL;
1630 }
1631
1632 void FrameLoader::reloadWithOverrideEncoding(const String& encoding)
1633 {
1634     if (!m_documentLoader)
1635         return;
1636
1637     ResourceRequest request = m_documentLoader->request();
1638     URL unreachableURL = m_documentLoader->unreachableURL();
1639     if (!unreachableURL.isEmpty())
1640         request.setURL(unreachableURL);
1641
1642     // FIXME: If the resource is a result of form submission and is not cached, the form will be silently resubmitted.
1643     // We should ask the user for confirmation in this case.
1644     request.setCachePolicy(ReturnCacheDataElseLoad);
1645
1646     Ref<DocumentLoader> loader = m_client.createDocumentLoader(request, defaultSubstituteDataForURL(request.url()));
1647     applyShouldOpenExternalURLsPolicyToNewDocumentLoader(m_frame, loader, InitiatedByMainFrame::Unknown, m_documentLoader->shouldOpenExternalURLsPolicyToPropagate());
1648
1649     setPolicyDocumentLoader(loader.ptr());
1650
1651     loader->setOverrideEncoding(encoding);
1652
1653     loadWithDocumentLoader(loader.ptr(), FrameLoadType::Reload, 0, AllowNavigationToInvalidURL::Yes, NavigationPolicyCheck::Require, [] { });
1654 }
1655
1656 void FrameLoader::reload(OptionSet<ReloadOption> options)
1657 {
1658     if (!m_documentLoader)
1659         return;
1660
1661     // If a window is created by javascript, its main frame can have an empty but non-nil URL.
1662     // Reloading in this case will lose the current contents (see 4151001).
1663     if (m_documentLoader->request().url().isEmpty())
1664         return;
1665
1666     // Replace error-page URL with the URL we were trying to reach.
1667     ResourceRequest initialRequest = m_documentLoader->request();
1668     URL unreachableURL = m_documentLoader->unreachableURL();
1669     if (!unreachableURL.isEmpty())
1670         initialRequest.setURL(unreachableURL);
1671
1672     // Create a new document loader for the reload, this will become m_documentLoader eventually,
1673     // but first it has to be the "policy" document loader, and then the "provisional" document loader.
1674     Ref<DocumentLoader> loader = m_client.createDocumentLoader(initialRequest, defaultSubstituteDataForURL(initialRequest.url()));
1675     applyShouldOpenExternalURLsPolicyToNewDocumentLoader(m_frame, loader, InitiatedByMainFrame::Unknown, m_documentLoader->shouldOpenExternalURLsPolicyToPropagate());
1676
1677     loader->setUserContentExtensionsEnabled(!options.contains(ReloadOption::DisableContentBlockers));
1678     
1679     ResourceRequest& request = loader->request();
1680
1681     // FIXME: We don't have a mechanism to revalidate the main resource without reloading at the moment.
1682     request.setCachePolicy(ReloadIgnoringCacheData);
1683
1684     addSameSiteInfoToRequestIfNeeded(request);
1685
1686     // If we're about to re-post, set up action so the application can warn the user.
1687     if (request.httpMethod() == "POST")
1688         loader->setTriggeringAction({ *m_frame.document(), request, InitiatedByMainFrame::Unknown, NavigationType::FormResubmitted });
1689
1690     loader->setOverrideEncoding(m_documentLoader->overrideEncoding());
1691
1692     auto frameLoadTypeForReloadOptions = [] (auto options) {
1693         if (options.contains(ReloadOption::FromOrigin))
1694             return FrameLoadType::ReloadFromOrigin;
1695         if (options.contains(ReloadOption::ExpiredOnly))
1696             return FrameLoadType::ReloadExpiredOnly;
1697         return FrameLoadType::Reload;
1698     };
1699     
1700     loadWithDocumentLoader(loader.ptr(), frameLoadTypeForReloadOptions(options), 0, AllowNavigationToInvalidURL::Yes, NavigationPolicyCheck::Require, [] { });
1701 }
1702
1703 void FrameLoader::stopAllLoaders(ClearProvisionalItemPolicy clearProvisionalItemPolicy)
1704 {
1705     ASSERT(!m_frame.document() || m_frame.document()->pageCacheState() != Document::InPageCache);
1706     if (!isStopLoadingAllowed())
1707         return;
1708
1709     // If this method is called from within this method, infinite recursion can occur (3442218). Avoid this.
1710     if (m_inStopAllLoaders)
1711         return;
1712
1713     // This method might dispatch events.
1714     RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(ScriptDisallowedScope::InMainThread::isScriptAllowed());
1715
1716     // Calling stopLoading() on the provisional document loader can blow away
1717     // the frame from underneath.
1718     Ref<Frame> protect(m_frame);
1719
1720     m_inStopAllLoaders = true;
1721
1722     policyChecker().stopCheck();
1723
1724     // If no new load is in progress, we should clear the provisional item from history
1725     // before we call stopLoading.
1726     if (clearProvisionalItemPolicy == ShouldClearProvisionalItem)
1727         history().setProvisionalItem(nullptr);
1728
1729     for (RefPtr<Frame> child = m_frame.tree().firstChild(); child; child = child->tree().nextSibling())
1730         child->loader().stopAllLoaders(clearProvisionalItemPolicy);
1731     if (m_provisionalDocumentLoader)
1732         m_provisionalDocumentLoader->stopLoading();
1733     if (m_documentLoader)
1734         m_documentLoader->stopLoading();
1735
1736     setProvisionalDocumentLoader(nullptr);
1737
1738     m_checkTimer.stop();
1739
1740     m_inStopAllLoaders = false;    
1741 }
1742
1743 void FrameLoader::stopForUserCancel(bool deferCheckLoadComplete)
1744 {
1745     // Calling stopAllLoaders can cause the frame to be deallocated, including the frame loader.
1746     Ref<Frame> protectedFrame(m_frame);
1747
1748     stopAllLoaders();
1749
1750 #if PLATFORM(IOS)
1751     // Lay out immediately when stopping to immediately clear the old page if we just committed this one
1752     // but haven't laid out/painted yet.
1753     // FIXME: Is this behavior specific to iOS? Or should we expose a setting to toggle this behavior?
1754     if (m_frame.view() && !m_frame.view()->didFirstLayout())
1755         m_frame.view()->layoutContext().layout();
1756 #endif
1757
1758     if (deferCheckLoadComplete)
1759         scheduleCheckLoadComplete();
1760     else if (m_frame.page())
1761         checkLoadComplete();
1762 }
1763
1764 DocumentLoader* FrameLoader::activeDocumentLoader() const
1765 {
1766     if (m_state == FrameStateProvisional)
1767         return m_provisionalDocumentLoader.get();
1768     return m_documentLoader.get();
1769 }
1770
1771 bool FrameLoader::isLoading() const
1772 {
1773     DocumentLoader* docLoader = activeDocumentLoader();
1774     if (!docLoader)
1775         return false;
1776     return docLoader->isLoading();
1777 }
1778
1779 bool FrameLoader::frameHasLoaded() const
1780 {
1781     return m_stateMachine.committedFirstRealDocumentLoad() || (m_provisionalDocumentLoader && !m_stateMachine.creatingInitialEmptyDocument()); 
1782 }
1783
1784 void FrameLoader::setDocumentLoader(DocumentLoader* loader)
1785 {
1786     if (!loader && !m_documentLoader)
1787         return;
1788     
1789     ASSERT(loader != m_documentLoader);
1790     ASSERT(!loader || loader->frameLoader() == this);
1791
1792     m_client.prepareForDataSourceReplacement();
1793     detachChildren();
1794
1795     // detachChildren() can trigger this frame's unload event, and therefore
1796     // script can run and do just about anything. For example, an unload event that calls
1797     // document.write("") on its parent frame can lead to a recursive detachChildren()
1798     // invocation for this frame. In that case, we can end up at this point with a
1799     // loader that hasn't been deleted but has been detached from its frame. Such a
1800     // DocumentLoader has been sufficiently detached that we'll end up in an inconsistent
1801     // state if we try to use it.
1802     if (loader && !loader->frame())
1803         return;
1804
1805     if (m_documentLoader)
1806         m_documentLoader->detachFromFrame();
1807
1808     m_documentLoader = loader;
1809 }
1810
1811 void FrameLoader::setPolicyDocumentLoader(DocumentLoader* loader)
1812 {
1813     if (m_policyDocumentLoader == loader)
1814         return;
1815
1816     if (loader)
1817         loader->attachToFrame(m_frame);
1818     if (m_policyDocumentLoader
1819             && m_policyDocumentLoader != m_provisionalDocumentLoader
1820             && m_policyDocumentLoader != m_documentLoader)
1821         m_policyDocumentLoader->detachFromFrame();
1822
1823     m_policyDocumentLoader = loader;
1824 }
1825
1826 void FrameLoader::setProvisionalDocumentLoader(DocumentLoader* loader)
1827 {
1828     ASSERT(!loader || !m_provisionalDocumentLoader);
1829     ASSERT(!loader || loader->frameLoader() == this);
1830
1831     if (m_provisionalDocumentLoader && m_provisionalDocumentLoader != m_documentLoader)
1832         m_provisionalDocumentLoader->detachFromFrame();
1833
1834     m_provisionalDocumentLoader = loader;
1835 }
1836
1837 void FrameLoader::setState(FrameState newState)
1838 {
1839     FrameState oldState = m_state;
1840     m_state = newState;
1841     
1842     if (newState == FrameStateProvisional)
1843         provisionalLoadStarted();
1844     else if (newState == FrameStateComplete) {
1845         frameLoadCompleted();
1846         if (m_documentLoader)
1847             m_documentLoader->stopRecordingResponses();
1848         if (m_frame.isMainFrame() && oldState != newState)
1849             m_frame.page()->performanceLogging().didReachPointOfInterest(PerformanceLogging::MainFrameLoadCompleted);
1850     }
1851 }
1852
1853 void FrameLoader::clearProvisionalLoad()
1854 {
1855     setProvisionalDocumentLoader(nullptr);
1856     m_progressTracker->progressCompleted();
1857     setState(FrameStateComplete);
1858 }
1859
1860 void FrameLoader::commitProvisionalLoad()
1861 {
1862     RefPtr<DocumentLoader> pdl = m_provisionalDocumentLoader;
1863     Ref<Frame> protect(m_frame);
1864
1865     std::unique_ptr<CachedPage> cachedPage;
1866     if (m_loadingFromCachedPage && history().provisionalItem())
1867         cachedPage = PageCache::singleton().take(*history().provisionalItem(), m_frame.page());
1868
1869     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(),
1870         m_frame.document() ? m_frame.document()->url().stringCenterEllipsizedToLength().utf8().data() : "",
1871         pdl ? pdl->url().stringCenterEllipsizedToLength().utf8().data() : "<no provisional DocumentLoader>", cachedPage.get());
1872
1873     willTransitionToCommitted();
1874
1875     if (!m_frame.tree().parent() && history().currentItem()) {
1876         // Check to see if we need to cache the page we are navigating away from into the back/forward cache.
1877         // We are doing this here because we know for sure that a new page is about to be loaded.
1878         PageCache::singleton().addIfCacheable(*history().currentItem(), m_frame.page());
1879         
1880         WebCore::jettisonExpensiveObjectsOnTopLevelNavigation();
1881     }
1882
1883     if (m_loadType != FrameLoadType::Replace)
1884         closeOldDataSources();
1885
1886     if (!cachedPage && !m_stateMachine.creatingInitialEmptyDocument())
1887         m_client.makeRepresentation(pdl.get());
1888
1889     transitionToCommitted(cachedPage.get());
1890
1891     if (pdl && m_documentLoader) {
1892         // Check if the destination page is allowed to access the previous page's timing information.
1893         Ref<SecurityOrigin> securityOrigin(SecurityOrigin::create(pdl->request().url()));
1894         m_documentLoader->timing().setHasSameOriginAsPreviousDocument(securityOrigin.get().canRequest(m_previousURL));
1895     }
1896
1897     // Call clientRedirectCancelledOrFinished() here so that the frame load delegate is notified that the redirect's
1898     // status has changed, if there was a redirect.  The frame load delegate may have saved some state about
1899     // the redirect in its -webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:.  Since we are
1900     // just about to commit a new page, there cannot possibly be a pending redirect at this point.
1901     if (m_sentRedirectNotification)
1902         clientRedirectCancelledOrFinished(false);
1903     
1904     if (cachedPage && cachedPage->document()) {
1905 #if PLATFORM(IOS)
1906         // FIXME: CachedPage::restore() would dispatch viewport change notification. However UIKit expects load
1907         // commit to happen before any changes to viewport arguments and dealing with this there is difficult.
1908         m_frame.page()->chrome().setDispatchViewportDataDidChangeSuppressed(true);
1909 #endif
1910         willRestoreFromCachedPage();
1911
1912         // Start request for the main resource and dispatch didReceiveResponse before the load is committed for
1913         // consistency with all other loads. See https://bugs.webkit.org/show_bug.cgi?id=150927.
1914         ResourceError mainResouceError;
1915         unsigned long mainResourceIdentifier;
1916         ResourceRequest mainResourceRequest(cachedPage->documentLoader()->request());
1917         requestFromDelegate(mainResourceRequest, mainResourceIdentifier, mainResouceError);
1918         notifier().dispatchDidReceiveResponse(cachedPage->documentLoader(), mainResourceIdentifier, cachedPage->documentLoader()->response());
1919
1920         std::optional<HasInsecureContent> hasInsecureContent = cachedPage->cachedMainFrame()->hasInsecureContent();
1921
1922         // FIXME: This API should be turned around so that we ground CachedPage into the Page.
1923         cachedPage->restore(*m_frame.page());
1924
1925         dispatchDidCommitLoad(hasInsecureContent);
1926
1927 #if PLATFORM(IOS)
1928         m_frame.page()->chrome().setDispatchViewportDataDidChangeSuppressed(false);
1929         m_frame.page()->chrome().dispatchViewportPropertiesDidChange(m_frame.page()->viewportArguments());
1930 #endif
1931
1932         auto& title = m_documentLoader->title();
1933         if (!title.string.isNull())
1934             m_client.dispatchDidReceiveTitle(title);
1935
1936         // Send remaining notifications for the main resource.
1937         notifier().sendRemainingDelegateMessages(m_documentLoader.get(), mainResourceIdentifier, mainResourceRequest, ResourceResponse(),
1938             nullptr, static_cast<int>(m_documentLoader->response().expectedContentLength()), 0, mainResouceError);
1939
1940         checkCompleted();
1941     } else
1942         didOpenURL();
1943
1944     LOG(Loading, "WebCoreLoading %s: Finished committing provisional load to URL %s", m_frame.tree().uniqueName().string().utf8().data(),
1945         m_frame.document() ? m_frame.document()->url().stringCenterEllipsizedToLength().utf8().data() : "");
1946
1947     if (m_loadType == FrameLoadType::Standard && m_documentLoader->isClientRedirect())
1948         history().updateForClientRedirect();
1949
1950     if (m_loadingFromCachedPage) {
1951         // Note, didReceiveDocType is expected to be called for cached pages. See <rdar://problem/5906758> for more details.
1952         if (auto* page = m_frame.page())
1953             page->chrome().didReceiveDocType(m_frame);
1954         m_frame.document()->resume(ActiveDOMObject::PageCache);
1955
1956         // Force a layout to update view size and thereby update scrollbars.
1957 #if PLATFORM(IOS)
1958         if (!m_client.forceLayoutOnRestoreFromPageCache())
1959             m_frame.view()->forceLayout();
1960 #else
1961         m_frame.view()->forceLayout();
1962 #endif
1963
1964         // Main resource delegates were already sent, so we skip the first response here.
1965         for (unsigned i = 1; i < m_documentLoader->responses().size(); ++i) {
1966             const auto& response = m_documentLoader->responses()[i];
1967             // FIXME: If the WebKit client changes or cancels the request, this is not respected.
1968             ResourceError error;
1969             unsigned long identifier;
1970             ResourceRequest request(response.url());
1971             requestFromDelegate(request, identifier, error);
1972             // FIXME: If we get a resource with more than 2B bytes, this code won't do the right thing.
1973             // However, with today's computers and networking speeds, this won't happen in practice.
1974             // Could be an issue with a giant local file.
1975             notifier().sendRemainingDelegateMessages(m_documentLoader.get(), identifier, request, response, 0, static_cast<int>(response.expectedContentLength()), 0, error);
1976         }
1977
1978         // FIXME: Why only this frame and not parent frames?
1979         checkLoadCompleteForThisFrame();
1980     }
1981 }
1982
1983 void FrameLoader::transitionToCommitted(CachedPage* cachedPage)
1984 {
1985     ASSERT(m_client.hasWebView());
1986     ASSERT(m_state == FrameStateProvisional);
1987
1988     if (m_state != FrameStateProvisional)
1989         return;
1990
1991     if (FrameView* view = m_frame.view()) {
1992         if (ScrollAnimator* scrollAnimator = view->existingScrollAnimator())
1993             scrollAnimator->cancelAnimations();
1994     }
1995
1996     m_client.setCopiesOnScroll();
1997     history().updateForCommit();
1998
1999     // The call to closeURL() invokes the unload event handler, which can execute arbitrary
2000     // JavaScript. If the script initiates a new load, we need to abandon the current load,
2001     // or the two will stomp each other.
2002     DocumentLoader* pdl = m_provisionalDocumentLoader.get();
2003     if (m_documentLoader)
2004         closeURL();
2005     if (pdl != m_provisionalDocumentLoader)
2006         return;
2007
2008     if (m_documentLoader)
2009         m_documentLoader->stopLoadingSubresources();
2010     if (m_documentLoader)
2011         m_documentLoader->stopLoadingPlugIns();
2012
2013     // Setting our document loader invokes the unload event handler of our child frames.
2014     // Script can do anything. If the script initiates a new load, we need to abandon the
2015     // current load or the two will stomp each other.
2016     setDocumentLoader(m_provisionalDocumentLoader.get());
2017     if (pdl != m_provisionalDocumentLoader)
2018         return;
2019     setProvisionalDocumentLoader(nullptr);
2020
2021     // Nothing else can interrupt this commit - set the Provisional->Committed transition in stone
2022     setState(FrameStateCommittedPage);
2023
2024     // Handle adding the URL to the back/forward list.
2025     DocumentLoader* dl = m_documentLoader.get();
2026
2027     switch (m_loadType) {
2028     case FrameLoadType::Forward:
2029     case FrameLoadType::Back:
2030     case FrameLoadType::IndexedBackForward:
2031         if (m_frame.page()) {
2032             // If the first load within a frame is a navigation within a back/forward list that was attached
2033             // without any of the items being loaded then we need to update the history in a similar manner as
2034             // for a standard load with the exception of updating the back/forward list (<rdar://problem/8091103>).
2035             if (!m_stateMachine.committedFirstRealDocumentLoad() && m_frame.isMainFrame())
2036                 history().updateForStandardLoad(HistoryController::UpdateAllExceptBackForwardList);
2037
2038             history().updateForBackForwardNavigation();
2039
2040             // For cached pages, CachedFrame::restore will take care of firing the popstate event with the history item's state object
2041             if (history().currentItem() && !cachedPage)
2042                 m_pendingStateObject = history().currentItem()->stateObject();
2043
2044             // Create a document view for this document, or used the cached view.
2045             if (cachedPage) {
2046                 DocumentLoader* cachedDocumentLoader = cachedPage->documentLoader();
2047                 ASSERT(cachedDocumentLoader);
2048                 cachedDocumentLoader->attachToFrame(m_frame);
2049                 m_client.transitionToCommittedFromCachedFrame(cachedPage->cachedMainFrame());
2050             } else
2051                 m_client.transitionToCommittedForNewPage();
2052         }
2053         break;
2054
2055     case FrameLoadType::Reload:
2056     case FrameLoadType::ReloadFromOrigin:
2057     case FrameLoadType::ReloadExpiredOnly:
2058     case FrameLoadType::Same:
2059     case FrameLoadType::Replace:
2060         history().updateForReload();
2061         m_client.transitionToCommittedForNewPage();
2062         break;
2063
2064     case FrameLoadType::Standard:
2065         history().updateForStandardLoad();
2066         if (m_frame.view())
2067             m_frame.view()->setScrollbarsSuppressed(true);
2068         m_client.transitionToCommittedForNewPage();
2069         break;
2070
2071     case FrameLoadType::RedirectWithLockedBackForwardList:
2072         history().updateForRedirectWithLockedBackForwardList();
2073         m_client.transitionToCommittedForNewPage();
2074         break;
2075     }
2076
2077     m_documentLoader->writer().setMIMEType(dl->responseMIMEType());
2078
2079     // Tell the client we've committed this URL.
2080     ASSERT(m_frame.view());
2081
2082     if (m_stateMachine.creatingInitialEmptyDocument())
2083         return;
2084
2085     if (!m_stateMachine.committedFirstRealDocumentLoad())
2086         m_stateMachine.advanceTo(FrameLoaderStateMachine::DisplayingInitialEmptyDocumentPostCommit);
2087 }
2088
2089 void FrameLoader::clientRedirectCancelledOrFinished(bool cancelWithLoadInProgress)
2090 {
2091     // Note that -webView:didCancelClientRedirectForFrame: is called on the frame load delegate even if
2092     // the redirect succeeded.  We should either rename this API, or add a new method, like
2093     // -webView:didFinishClientRedirectForFrame:
2094     m_client.dispatchDidCancelClientRedirect();
2095
2096     if (!cancelWithLoadInProgress)
2097         m_quickRedirectComing = false;
2098
2099     m_sentRedirectNotification = false;
2100 }
2101
2102 void FrameLoader::clientRedirected(const URL& url, double seconds, WallTime fireDate, LockBackForwardList lockBackForwardList)
2103 {
2104     m_client.dispatchWillPerformClientRedirect(url, seconds, fireDate);
2105     
2106     // Remember that we sent a redirect notification to the frame load delegate so that when we commit
2107     // the next provisional load, we can send a corresponding -webView:didCancelClientRedirectForFrame:
2108     m_sentRedirectNotification = true;
2109     
2110     // If a "quick" redirect comes in, we set a special mode so we treat the next
2111     // load as part of the original navigation. If we don't have a document loader, we have
2112     // no "original" load on which to base a redirect, so we treat the redirect as a normal load.
2113     // Loads triggered by JavaScript form submissions never count as quick redirects.
2114     m_quickRedirectComing = (lockBackForwardList == LockBackForwardList::Yes || history().currentItemShouldBeReplaced()) && m_documentLoader && !m_isExecutingJavaScriptFormAction;
2115 }
2116
2117 bool FrameLoader::shouldReload(const URL& currentURL, const URL& destinationURL)
2118 {
2119     // This function implements the rule: "Don't reload if navigating by fragment within
2120     // the same URL, but do reload if going to a new URL or to the same URL with no
2121     // fragment identifier at all."
2122     if (!destinationURL.hasFragmentIdentifier())
2123         return true;
2124     return !equalIgnoringFragmentIdentifier(currentURL, destinationURL);
2125 }
2126
2127 void FrameLoader::closeOldDataSources()
2128 {
2129     // FIXME: Is it important for this traversal to be postorder instead of preorder?
2130     // If so, add helpers for postorder traversal, and use them. If not, then lets not
2131     // use a recursive algorithm here.
2132     for (Frame* child = m_frame.tree().firstChild(); child; child = child->tree().nextSibling())
2133         child->loader().closeOldDataSources();
2134     
2135     if (m_documentLoader)
2136         m_client.dispatchWillClose();
2137
2138     m_client.setMainFrameDocumentReady(false); // stop giving out the actual DOMDocument to observers
2139 }
2140
2141 void FrameLoader::willRestoreFromCachedPage()
2142 {
2143     ASSERT(!m_frame.tree().parent());
2144     ASSERT(m_frame.page());
2145     ASSERT(m_frame.isMainFrame());
2146
2147     m_frame.navigationScheduler().cancel();
2148
2149     // We still have to close the previous part page.
2150     closeURL();
2151     
2152     // Delete old status bar messages (if it _was_ activated on last URL).
2153     if (m_frame.script().canExecuteScripts(NotAboutToExecuteScript)) {
2154         DOMWindow* window = m_frame.document()->domWindow();
2155         window->setStatus(String());
2156         window->setDefaultStatus(String());
2157     }
2158 }
2159
2160 void FrameLoader::open(CachedFrameBase& cachedFrame)
2161 {
2162     m_isComplete = false;
2163     
2164     // Don't re-emit the load event.
2165     m_didCallImplicitClose = true;
2166
2167     URL url = cachedFrame.url();
2168
2169     // FIXME: I suspect this block of code doesn't do anything.
2170     if (url.protocolIsInHTTPFamily() && !url.host().isEmpty() && url.path().isEmpty())
2171         url.setPath("/");
2172
2173     started();
2174     Document* document = cachedFrame.document();
2175     ASSERT(document);
2176     ASSERT(document->domWindow());
2177
2178     clear(document, true, true, cachedFrame.isMainFrame());
2179
2180     document->setPageCacheState(Document::NotInPageCache);
2181
2182     m_needsClear = true;
2183     m_isComplete = false;
2184     m_didCallImplicitClose = false;
2185     m_outgoingReferrer = url.string();
2186
2187     FrameView* view = cachedFrame.view();
2188     
2189     // When navigating to a CachedFrame its FrameView should never be null.  If it is we'll crash in creative ways downstream.
2190     ASSERT(view);
2191     view->setWasScrolledByUser(false);
2192
2193     std::optional<IntRect> previousViewFrameRect = m_frame.view() ?  m_frame.view()->frameRect() : std::optional<IntRect>(std::nullopt);
2194     m_frame.setView(view);
2195
2196     // Use the previous ScrollView's frame rect.
2197     if (previousViewFrameRect)
2198         view->setFrameRect(previousViewFrameRect.value());
2199     
2200     m_frame.setDocument(document);
2201     document->domWindow()->resumeFromDocumentSuspension();
2202
2203     updateFirstPartyForCookies();
2204
2205     cachedFrame.restore();
2206 }
2207
2208 bool FrameLoader::isHostedByObjectElement() const
2209 {
2210     HTMLFrameOwnerElement* owner = m_frame.ownerElement();
2211     return owner && owner->hasTagName(objectTag);
2212 }
2213
2214 bool FrameLoader::isReplacing() const
2215 {
2216     return m_loadType == FrameLoadType::Replace;
2217 }
2218
2219 void FrameLoader::setReplacing()
2220 {
2221     m_loadType = FrameLoadType::Replace;
2222 }
2223
2224 bool FrameLoader::subframeIsLoading() const
2225 {
2226     // It's most likely that the last added frame is the last to load so we walk backwards.
2227     for (Frame* child = m_frame.tree().lastChild(); child; child = child->tree().previousSibling()) {
2228         FrameLoader& childLoader = child->loader();
2229         DocumentLoader* documentLoader = childLoader.documentLoader();
2230         if (documentLoader && documentLoader->isLoadingInAPISense())
2231             return true;
2232         documentLoader = childLoader.provisionalDocumentLoader();
2233         if (documentLoader && documentLoader->isLoadingInAPISense())
2234             return true;
2235         documentLoader = childLoader.policyDocumentLoader();
2236         if (documentLoader)
2237             return true;
2238     }
2239     return false;
2240 }
2241
2242 void FrameLoader::willChangeTitle(DocumentLoader* loader)
2243 {
2244     m_client.willChangeTitle(loader);
2245 }
2246
2247 FrameLoadType FrameLoader::loadType() const
2248 {
2249     return m_loadType;
2250 }
2251     
2252 CachePolicy FrameLoader::subresourceCachePolicy(const URL& url) const
2253 {
2254     if (Page* page = m_frame.page()) {
2255         if (page->isResourceCachingDisabled())
2256             return CachePolicyReload;
2257     }
2258
2259     if (m_isComplete)
2260         return CachePolicyVerify;
2261
2262     if (m_loadType == FrameLoadType::ReloadFromOrigin)
2263         return CachePolicyReload;
2264
2265     if (Frame* parentFrame = m_frame.tree().parent()) {
2266         CachePolicy parentCachePolicy = parentFrame->loader().subresourceCachePolicy(url);
2267         if (parentCachePolicy != CachePolicyVerify)
2268             return parentCachePolicy;
2269     }
2270     
2271     switch (m_loadType) {
2272     case FrameLoadType::Reload:
2273         return CachePolicyRevalidate;
2274     case FrameLoadType::Back:
2275     case FrameLoadType::Forward:
2276     case FrameLoadType::IndexedBackForward:
2277         return CachePolicyHistoryBuffer;
2278     case FrameLoadType::ReloadFromOrigin:
2279         ASSERT_NOT_REACHED(); // Already handled above.
2280         return CachePolicyReload;
2281     case FrameLoadType::RedirectWithLockedBackForwardList:
2282     case FrameLoadType::Replace:
2283     case FrameLoadType::Same:
2284     case FrameLoadType::Standard:
2285         return CachePolicyVerify;
2286     case FrameLoadType::ReloadExpiredOnly:
2287         // We know about expiration for HTTP and data. Do a normal reload otherwise.
2288         if (!url.protocolIsInHTTPFamily() && !url.protocolIsData())
2289             return CachePolicyReload;
2290         return CachePolicyVerify;
2291     }
2292
2293     RELEASE_ASSERT_NOT_REACHED();
2294     return CachePolicyVerify;
2295 }
2296
2297 void FrameLoader::checkLoadCompleteForThisFrame()
2298 {
2299     ASSERT(m_client.hasWebView());
2300
2301     // FIXME: Should this check be done in checkLoadComplete instead of here?
2302     // FIXME: Why does this one check need to be repeated here, and not the many others from checkCompleted?
2303     if (m_frame.document()->isDelayingLoadEvent())
2304         return;
2305
2306     switch (m_state) {
2307         case FrameStateProvisional: {
2308             // FIXME: Prohibiting any provisional load failures from being sent to clients
2309             // while handling provisional load failures is too heavy. For example, the current
2310             // load will fail to cancel another ongoing load. That might prevent clients' page
2311             // load state being handled properly.
2312             if (!m_provisionalLoadErrorBeingHandledURL.isEmpty())
2313                 return;
2314
2315             RefPtr<DocumentLoader> pdl = m_provisionalDocumentLoader;
2316             if (!pdl)
2317                 return;
2318                 
2319             // If we've received any errors we may be stuck in the provisional state and actually complete.
2320             const ResourceError& error = pdl->mainDocumentError();
2321             if (error.isNull())
2322                 return;
2323
2324             // Check all children first.
2325             RefPtr<HistoryItem> item;
2326             if (Page* page = m_frame.page())
2327                 if (isBackForwardLoadType(loadType()))
2328                     // Reset the back forward list to the last committed history item at the top level.
2329                     item = page->mainFrame().loader().history().currentItem();
2330                 
2331             // Only reset if we aren't already going to a new provisional item.
2332             bool shouldReset = !history().provisionalItem();
2333             if (!pdl->isLoadingInAPISense() || pdl->isStopping()) {
2334                 m_provisionalLoadErrorBeingHandledURL = m_provisionalDocumentLoader->url();
2335                 m_client.dispatchDidFailProvisionalLoad(error);
2336 #if ENABLE(CONTENT_FILTERING)
2337                 if (auto contentFilter = pdl->contentFilter())
2338                     contentFilter->handleProvisionalLoadFailure(error);
2339 #endif
2340                 m_provisionalLoadErrorBeingHandledURL = { };
2341
2342                 ASSERT(!pdl->isLoading());
2343
2344                 // If we're in the middle of loading multipart data, we need to restore the document loader.
2345                 if (isReplacing() && !m_documentLoader.get())
2346                     setDocumentLoader(m_provisionalDocumentLoader.get());
2347
2348                 // Finish resetting the load state, but only if another load hasn't been started by the
2349                 // delegate callback.
2350                 if (pdl == m_provisionalDocumentLoader)
2351                     clearProvisionalLoad();
2352                 else if (activeDocumentLoader()) {
2353                     URL unreachableURL = activeDocumentLoader()->unreachableURL();
2354                     if (!unreachableURL.isEmpty() && unreachableURL == pdl->request().url())
2355                         shouldReset = false;
2356                 }
2357             }
2358             if (shouldReset && item)
2359                 if (Page* page = m_frame.page()) {
2360                     page->backForward().setCurrentItem(item.get());
2361                     m_frame.loader().client().updateGlobalHistoryItemForPage();
2362                 }
2363             return;
2364         }
2365         
2366         case FrameStateCommittedPage: {
2367             DocumentLoader* dl = m_documentLoader.get();            
2368             if (!dl || (dl->isLoadingInAPISense() && !dl->isStopping()))
2369                 return;
2370
2371             setState(FrameStateComplete);
2372
2373             // FIXME: Is this subsequent work important if we already navigated away?
2374             // Maybe there are bugs because of that, or extra work we can skip because
2375             // the new page is ready.
2376
2377             m_client.forceLayoutForNonHTML();
2378              
2379             // If the user had a scroll point, scroll to it, overriding the anchor point if any.
2380             if (m_frame.page()) {
2381                 if (isBackForwardLoadType(m_loadType) || isReload(m_loadType))
2382                     history().restoreScrollPositionAndViewState();
2383             }
2384
2385             if (m_stateMachine.creatingInitialEmptyDocument() || !m_stateMachine.committedFirstRealDocumentLoad())
2386                 return;
2387
2388             m_progressTracker->progressCompleted();
2389             Page* page = m_frame.page();
2390             if (page) {
2391                 if (m_frame.isMainFrame()) {
2392                     tracePoint(MainResourceLoadDidEnd);
2393                     page->didFinishLoad();
2394                 }
2395             }
2396
2397             const ResourceError& error = dl->mainDocumentError();
2398
2399             AXObjectCache::AXLoadingEvent loadingEvent;
2400             if (!error.isNull()) {
2401                 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());
2402                 m_client.dispatchDidFailLoad(error);
2403                 loadingEvent = AXObjectCache::AXLoadingFailed;
2404             } else {
2405                 RELEASE_LOG_IF_ALLOWED("checkLoadCompleteForThisFrame: Finished frame load (frame = %p, main = %d)", &m_frame, m_frame.isMainFrame());
2406 #if ENABLE(DATA_DETECTION)
2407                 auto* document = m_frame.document();
2408                 if (m_frame.settings().dataDetectorTypes() != DataDetectorTypeNone && document) {
2409                     if (auto* documentElement = document->documentElement()) {
2410                         RefPtr<Range> documentRange = makeRange(firstPositionInNode(documentElement), lastPositionInNode(documentElement));
2411                         m_frame.setDataDetectionResults(DataDetection::detectContentInRange(documentRange, m_frame.settings().dataDetectorTypes(), m_client.dataDetectionContext()));
2412                         if (m_frame.isMainFrame())
2413                             m_client.dispatchDidFinishDataDetection(m_frame.dataDetectionResults());
2414                     }
2415                 }
2416 #endif
2417                 m_client.dispatchDidFinishLoad();
2418                 loadingEvent = AXObjectCache::AXLoadingFinished;
2419             }
2420
2421             // Notify accessibility.
2422             if (auto* document = m_frame.document()) {
2423                 if (AXObjectCache* cache = document->existingAXObjectCache())
2424                     cache->frameLoadingEventNotification(&m_frame, loadingEvent);
2425             }
2426
2427             // The above calls to dispatchDidFinishLoad() might have detached the Frame
2428             // from its Page and also might have caused Page to be deleted.
2429             // Don't assume 'page' is still available to use.
2430             if (m_frame.isMainFrame() && m_frame.page()) {
2431                 ASSERT(&m_frame.page()->mainFrame() == &m_frame);
2432                 m_frame.page()->diagnosticLoggingClient().logDiagnosticMessageWithResult(DiagnosticLoggingKeys::pageLoadedKey(), emptyString(), error.isNull() ? DiagnosticLoggingResultPass : DiagnosticLoggingResultFail, ShouldSample::Yes);
2433             }
2434
2435             return;
2436         }
2437         
2438         case FrameStateComplete:
2439             m_loadType = FrameLoadType::Standard;
2440             frameLoadCompleted();
2441             return;
2442     }
2443
2444     ASSERT_NOT_REACHED();
2445 }
2446
2447 void FrameLoader::setOriginalURLForDownloadRequest(ResourceRequest& request)
2448 {
2449     // FIXME: Rename firstPartyForCookies back to mainDocumentURL. It was a mistake to think that it was only used for cookies.
2450     // The originalURL is defined as the URL of the page where the download was initiated.
2451     URL originalURL;
2452     auto* initiator = m_frame.document();
2453     if (initiator) {
2454         originalURL = initiator->firstPartyForCookies();
2455         // If there is no main document URL, it means that this document is newly opened and just for download purpose.
2456         // In this case, we need to set the originalURL to this document's opener's main document URL.
2457         if (originalURL.isEmpty() && opener() && opener()->document()) {
2458             originalURL = opener()->document()->firstPartyForCookies();
2459             initiator = opener()->document();
2460         }
2461     }
2462     // If the originalURL is the same as the requested URL, we are processing a download
2463     // initiated directly without a page and do not need to specify the originalURL.
2464     if (originalURL == request.url())
2465         request.setFirstPartyForCookies(URL());
2466     else
2467         request.setFirstPartyForCookies(originalURL);
2468     addSameSiteInfoToRequestIfNeeded(request, initiator);
2469 }
2470
2471 void FrameLoader::didReachLayoutMilestone(LayoutMilestones milestones)
2472 {
2473     ASSERT(m_frame.isMainFrame());
2474
2475     m_client.dispatchDidReachLayoutMilestone(milestones);
2476 }
2477
2478 void FrameLoader::didFirstLayout()
2479 {
2480 #if PLATFORM(IOS)
2481     // Only send layout-related delegate callbacks synchronously for the main frame to
2482     // avoid reentering layout for the main frame while delivering a layout-related delegate
2483     // callback for a subframe.
2484     if (&m_frame != &m_frame.page()->mainFrame())
2485         return;
2486 #endif
2487     if (m_frame.page() && isBackForwardLoadType(m_loadType))
2488         history().restoreScrollPositionAndViewState();
2489
2490     if (m_stateMachine.committedFirstRealDocumentLoad() && !m_stateMachine.isDisplayingInitialEmptyDocument() && !m_stateMachine.firstLayoutDone())
2491         m_stateMachine.advanceTo(FrameLoaderStateMachine::FirstLayoutDone);
2492 }
2493
2494 void FrameLoader::frameLoadCompleted()
2495 {
2496     // Note: Can be called multiple times.
2497
2498     m_client.frameLoadCompleted();
2499
2500     history().updateForFrameLoadCompleted();
2501
2502     // After a canceled provisional load, firstLayoutDone is false.
2503     // Reset it to true if we're displaying a page.
2504     if (m_documentLoader && m_stateMachine.committedFirstRealDocumentLoad() && !m_stateMachine.isDisplayingInitialEmptyDocument() && !m_stateMachine.firstLayoutDone())
2505         m_stateMachine.advanceTo(FrameLoaderStateMachine::FirstLayoutDone);
2506 }
2507
2508 void FrameLoader::detachChildren()
2509 {
2510     // detachChildren() will fire the unload event in each subframe and the
2511     // HTML specification states that the parent document's ignore-opens-during-unload counter while
2512     // this event is being fired in its subframes:
2513     // https://html.spec.whatwg.org/multipage/browsers.html#unload-a-document
2514     IgnoreOpensDuringUnloadCountIncrementer ignoreOpensDuringUnloadCountIncrementer(m_frame.document());
2515
2516     // Any subframe inserted by unload event handlers executed in the loop below will not get unloaded
2517     // because we create a copy of the subframes list before looping. Therefore, it would be unsafe to
2518     // allow loading of subframes at this point.
2519     SubframeLoadingDisabler subframeLoadingDisabler(m_frame.document());
2520
2521     Vector<Ref<Frame>, 16> childrenToDetach;
2522     childrenToDetach.reserveInitialCapacity(m_frame.tree().childCount());
2523     for (Frame* child = m_frame.tree().lastChild(); child; child = child->tree().previousSibling())
2524         childrenToDetach.uncheckedAppend(*child);
2525     for (auto& child : childrenToDetach)
2526         child->loader().detachFromParent();
2527 }
2528
2529 void FrameLoader::closeAndRemoveChild(Frame& child)
2530 {
2531     child.tree().detachFromParent();
2532
2533     child.setView(nullptr);
2534     if (child.ownerElement() && child.page())
2535         child.page()->decrementSubframeCount();
2536     child.willDetachPage();
2537     child.detachFromPage();
2538
2539     m_frame.tree().removeChild(child);
2540 }
2541
2542 // Called every time a resource is completely loaded or an error is received.
2543 void FrameLoader::checkLoadComplete()
2544 {
2545     m_shouldCallCheckLoadComplete = false;
2546
2547     if (!m_frame.page())
2548         return;
2549
2550     ASSERT(m_client.hasWebView());
2551     
2552     // FIXME: Always traversing the entire frame tree is a bit inefficient, but 
2553     // is currently needed in order to null out the previous history item for all frames.
2554     Vector<Ref<Frame>, 16> frames;
2555     for (Frame* frame = &m_frame.mainFrame(); frame; frame = frame->tree().traverseNext())
2556         frames.append(*frame);
2557
2558     // To process children before their parents, iterate the vector backwards.
2559     for (auto frame = frames.rbegin(); frame != frames.rend(); ++frame) {
2560         if ((*frame)->page())
2561             (*frame)->loader().checkLoadCompleteForThisFrame();
2562     }
2563 }
2564
2565 int FrameLoader::numPendingOrLoadingRequests(bool recurse) const
2566 {
2567     if (!recurse)
2568         return m_frame.document()->cachedResourceLoader().requestCount();
2569
2570     int count = 0;
2571     for (Frame* frame = &m_frame; frame; frame = frame->tree().traverseNext(&m_frame))
2572         count += frame->document()->cachedResourceLoader().requestCount();
2573     return count;
2574 }
2575
2576 String FrameLoader::userAgent(const URL& url) const
2577 {
2578     return m_client.userAgent(url);
2579 }
2580
2581 void FrameLoader::dispatchOnloadEvents()
2582 {
2583     m_client.dispatchDidDispatchOnloadEvents();
2584
2585     if (documentLoader())
2586         documentLoader()->dispatchOnloadEvents();
2587 }
2588
2589 void FrameLoader::frameDetached()
2590 {
2591     // Calling stopAllLoaders() can cause the frame to be deallocated, including the frame loader.
2592     Ref<Frame> protectedFrame(m_frame);
2593
2594     if (m_frame.document()->pageCacheState() != Document::InPageCache) {
2595         stopAllLoaders();
2596         m_frame.document()->stopActiveDOMObjects();
2597     }
2598
2599     detachFromParent();
2600 }
2601
2602 void FrameLoader::detachFromParent()
2603 {
2604     // Calling stopAllLoaders() can cause the frame to be deallocated, including the frame loader.
2605     Ref<Frame> protect(m_frame);
2606
2607     closeURL();
2608     history().saveScrollPositionAndViewStateToItem(history().currentItem());
2609     detachChildren();
2610     if (m_frame.document()->pageCacheState() != Document::InPageCache) {
2611         // stopAllLoaders() needs to be called after detachChildren() if the document is not in the page cache,
2612         // because detachedChildren() will trigger the unload event handlers of any child frames, and those event
2613         // handlers might start a new subresource load in this frame.
2614         stopAllLoaders();
2615     }
2616
2617     InspectorInstrumentation::frameDetachedFromParent(m_frame);
2618
2619     detachViewsAndDocumentLoader();
2620
2621     m_progressTracker = nullptr;
2622
2623     if (Frame* parent = m_frame.tree().parent()) {
2624         parent->loader().closeAndRemoveChild(m_frame);
2625         parent->loader().scheduleCheckCompleted();
2626         parent->loader().scheduleCheckLoadComplete();
2627     } else {
2628         m_frame.setView(nullptr);
2629         m_frame.willDetachPage();
2630         m_frame.detachFromPage();
2631     }
2632 }
2633
2634 void FrameLoader::detachViewsAndDocumentLoader()
2635 {
2636     m_client.detachedFromParent2();
2637     setDocumentLoader(nullptr);
2638     m_client.detachedFromParent3();
2639 }
2640     
2641 void FrameLoader::addExtraFieldsToSubresourceRequest(ResourceRequest& request)
2642 {
2643     addExtraFieldsToRequest(request, m_loadType, false);
2644 }
2645
2646 void FrameLoader::addExtraFieldsToMainResourceRequest(ResourceRequest& request)
2647 {
2648     // FIXME: Using m_loadType seems wrong for some callers.
2649     // If we are only preparing to load the main resource, that is previous load's load type!
2650     addExtraFieldsToRequest(request, m_loadType, true);
2651
2652     // Upgrade-Insecure-Requests should only be added to main resource requests
2653     addHTTPUpgradeInsecureRequestsIfNeeded(request);
2654 }
2655
2656 ResourceRequestCachePolicy FrameLoader::defaultRequestCachingPolicy(const ResourceRequest& request, FrameLoadType loadType, bool isMainResource)
2657 {
2658     if (m_overrideCachePolicyForTesting)
2659         return m_overrideCachePolicyForTesting.value();
2660
2661     if (isMainResource) {
2662         if (isReload(loadType) || request.isConditional())
2663             return ReloadIgnoringCacheData;
2664
2665         return UseProtocolCachePolicy;
2666     }
2667
2668     if (request.isConditional())
2669         return ReloadIgnoringCacheData;
2670
2671     if (documentLoader()->isLoadingInAPISense()) {
2672         // If we inherit cache policy from a main resource, we use the DocumentLoader's
2673         // original request cache policy for two reasons:
2674         // 1. For POST requests, we mutate the cache policy for the main resource,
2675         //    but we do not want this to apply to subresources
2676         // 2. Delegates that modify the cache policy using willSendRequest: should
2677         //    not affect any other resources. Such changes need to be done
2678         //    per request.
2679         ResourceRequestCachePolicy mainDocumentOriginalCachePolicy = documentLoader()->originalRequest().cachePolicy();
2680         // 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.
2681         // This policy is set on initial request too, but should not be inherited.
2682         return (mainDocumentOriginalCachePolicy == ReturnCacheDataDontLoad) ? ReturnCacheDataElseLoad : mainDocumentOriginalCachePolicy;
2683     }
2684
2685     return UseProtocolCachePolicy;
2686 }
2687
2688 void FrameLoader::addExtraFieldsToRequest(ResourceRequest& request, FrameLoadType loadType, bool isMainResource)
2689 {
2690     // Don't set the cookie policy URL if it's already been set.
2691     // But make sure to set it on all requests regardless of protocol, as it has significance beyond the cookie policy (<rdar://problem/6616664>).
2692     if (request.firstPartyForCookies().isEmpty()) {
2693         if (isMainResource && m_frame.isMainFrame())
2694             request.setFirstPartyForCookies(request.url());
2695         else if (Document* document = m_frame.document())
2696             request.setFirstPartyForCookies(document->firstPartyForCookies());
2697     }
2698
2699     if (request.isSameSiteUnspecified()) {
2700         auto* initiator = m_frame.document();
2701         if (isMainResource) {
2702             auto* ownerFrame = m_frame.tree().parent();
2703             if (!ownerFrame)
2704                 ownerFrame = m_opener;
2705             if (ownerFrame)
2706                 initiator = ownerFrame->document();
2707             ASSERT(ownerFrame || m_frame.isMainFrame());
2708         }
2709         addSameSiteInfoToRequestIfNeeded(request, initiator);
2710         request.setIsTopSite(isMainResource && m_frame.isMainFrame());
2711     }
2712
2713     Page* page = frame().page();
2714     bool hasSpecificCachePolicy = request.cachePolicy() != UseProtocolCachePolicy;
2715
2716     if (page && page->isResourceCachingDisabled()) {
2717         request.setCachePolicy(ReloadIgnoringCacheData);
2718         loadType = FrameLoadType::ReloadFromOrigin;
2719     } else if (!hasSpecificCachePolicy)
2720         request.setCachePolicy(defaultRequestCachingPolicy(request, loadType, isMainResource));
2721
2722     // The remaining modifications are only necessary for HTTP and HTTPS.
2723     if (!request.url().isEmpty() && !request.url().protocolIsInHTTPFamily())
2724         return;
2725
2726     if (!hasSpecificCachePolicy && request.cachePolicy() == ReloadIgnoringCacheData) {
2727         if (loadType == FrameLoadType::Reload)
2728             request.setHTTPHeaderField(HTTPHeaderName::CacheControl, "max-age=0");
2729         else if (loadType == FrameLoadType::ReloadFromOrigin) {
2730             request.setHTTPHeaderField(HTTPHeaderName::CacheControl, "no-cache");
2731             request.setHTTPHeaderField(HTTPHeaderName::Pragma, "no-cache");
2732         }
2733     }
2734
2735     if (m_overrideResourceLoadPriorityForTesting)
2736         request.setPriority(m_overrideResourceLoadPriorityForTesting.value());
2737
2738     applyUserAgentIfNeeded(request);
2739
2740     if (isMainResource)
2741         request.setHTTPAccept(defaultAcceptHeader);
2742
2743     // Make sure we send the Origin header.
2744     addHTTPOriginIfNeeded(request, String());
2745
2746     // Only set fallback array if it's still empty (later attempts may be incorrect, see bug 117818).
2747     if (request.responseContentDispositionEncodingFallbackArray().isEmpty()) {
2748         // Always try UTF-8. If that fails, try frame encoding (if any) and then the default.
2749         request.setResponseContentDispositionEncodingFallbackArray("UTF-8", m_frame.document()->encoding(), m_frame.settings().defaultTextEncodingName());
2750     }
2751 }
2752
2753 void FrameLoader::addHTTPOriginIfNeeded(ResourceRequest& request, const String& origin)
2754 {
2755     if (!request.httpOrigin().isEmpty())
2756         return;  // Request already has an Origin header.
2757
2758     // Don't send an Origin header for GET or HEAD to avoid privacy issues.
2759     // For example, if an intranet page has a hyperlink to an external web
2760     // site, we don't want to include the Origin of the request because it
2761     // will leak the internal host name. Similar privacy concerns have lead
2762     // to the widespread suppression of the Referer header at the network
2763     // layer.
2764     if (request.httpMethod() == "GET" || request.httpMethod() == "HEAD")
2765         return;
2766
2767     // For non-GET and non-HEAD methods, always send an Origin header so the
2768     // server knows we support this feature.
2769
2770     if (origin.isEmpty()) {
2771         // If we don't know what origin header to attach, we attach the value
2772         // for an empty origin.
2773         request.setHTTPOrigin(SecurityOrigin::createUnique()->toString());
2774         return;
2775     }
2776
2777     request.setHTTPOrigin(origin);
2778 }
2779
2780 // Implements the "'Same-site' and 'cross-site' Requests" algorithm from <https://tools.ietf.org/html/draft-ietf-httpbis-cookie-same-site-00#section-2.1>.
2781 // The algorithm is ammended to treat URLs that inherit their security origin from their owner (e.g. about:blank)
2782 // as same-site. This matches the behavior of Chrome and Firefox.
2783 void FrameLoader::addSameSiteInfoToRequestIfNeeded(ResourceRequest& request, const Document* initiator)
2784 {
2785     if (!request.isSameSiteUnspecified())
2786         return;
2787     if (!initiator) {
2788         request.setIsSameSite(true);
2789         return;
2790     }
2791     if (SecurityPolicy::shouldInheritSecurityOriginFromOwner(request.url())) {
2792         request.setIsSameSite(true);
2793         return;
2794     }
2795     request.setIsSameSite(registrableDomainsAreEqual(initiator->firstPartyForSameSiteCookies(), request.url()));
2796 }
2797
2798 void FrameLoader::addHTTPUpgradeInsecureRequestsIfNeeded(ResourceRequest& request)
2799 {
2800     if (request.url().protocolIs("https")) {
2801         // FIXME: Identify HSTS cases and avoid adding the header. <https://bugs.webkit.org/show_bug.cgi?id=157885>
2802         return;
2803     }
2804
2805     request.setHTTPHeaderField(HTTPHeaderName::UpgradeInsecureRequests, ASCIILiteral("1"));
2806 }
2807
2808 void FrameLoader::loadPostRequest(FrameLoadRequest&& request, const String& referrer, FrameLoadType loadType, Event* event, FormState* formState, CompletionHandler<void()>&& completionHandler)
2809 {
2810     String frameName = request.frameName();
2811     LockHistory lockHistory = request.lockHistory();
2812     AllowNavigationToInvalidURL allowNavigationToInvalidURL = request.allowNavigationToInvalidURL();
2813     NewFrameOpenerPolicy openerPolicy = request.newFrameOpenerPolicy();
2814
2815     const ResourceRequest& inRequest = request.resourceRequest();
2816     const URL& url = inRequest.url();
2817     const String& contentType = inRequest.httpContentType();
2818     String origin = inRequest.httpOrigin();
2819
2820     ResourceRequest workingResourceRequest(url);    
2821
2822     if (!referrer.isEmpty())
2823         workingResourceRequest.setHTTPReferrer(referrer);
2824     workingResourceRequest.setHTTPOrigin(origin);
2825     workingResourceRequest.setHTTPMethod("POST");
2826     workingResourceRequest.setHTTPBody(inRequest.httpBody());
2827     workingResourceRequest.setHTTPContentType(contentType);
2828     addExtraFieldsToRequest(workingResourceRequest, loadType, true);
2829
2830     if (Document* document = m_frame.document())
2831         document->contentSecurityPolicy()->upgradeInsecureRequestIfNeeded(workingResourceRequest, ContentSecurityPolicy::InsecureRequestType::Load);
2832
2833     NavigationAction action { request.requester(), workingResourceRequest, request.initiatedByMainFrame(), loadType, true, event, request.shouldOpenExternalURLsPolicy(), request.downloadAttribute() };
2834
2835     if (!frameName.isEmpty()) {
2836         // The search for a target frame is done earlier in the case of form submission.
2837         if (Frame* targetFrame = formState ? 0 : findFrameForNavigation(frameName)) {
2838             targetFrame->loader().loadWithNavigationAction(workingResourceRequest, action, lockHistory, loadType, WTFMove(formState), allowNavigationToInvalidURL, WTFMove(completionHandler));
2839             return;
2840         }
2841
2842         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) {
2843             continueLoadAfterNewWindowPolicy(request, formState, frameName, action, shouldContinue, allowNavigationToInvalidURL, openerPolicy);
2844             completionHandler();
2845         });
2846         return;
2847     }
2848
2849     // must grab this now, since this load may stop the previous load and clear this flag
2850     bool isRedirect = m_quickRedirectComing;
2851     loadWithNavigationAction(workingResourceRequest, action, lockHistory, loadType, WTFMove(formState), allowNavigationToInvalidURL, [this, isRedirect, protectedFrame = makeRef(m_frame), completionHandler = WTFMove(completionHandler)] {
2852         if (isRedirect) {
2853             m_quickRedirectComing = false;
2854             if (m_provisionalDocumentLoader)
2855                 m_provisionalDocumentLoader->setIsClientRedirect(true);
2856             else if (m_policyDocumentLoader)
2857                 m_policyDocumentLoader->setIsClientRedirect(true);
2858         }
2859         completionHandler();
2860     });
2861 }
2862
2863 unsigned long FrameLoader::loadResourceSynchronously(const ResourceRequest& request, ClientCredentialPolicy clientCredentialPolicy, const FetchOptions& options, const HTTPHeaderMap& originalRequestHeaders, ResourceError& error, ResourceResponse& response, RefPtr<SharedBuffer>& data)
2864 {
2865     ASSERT(m_frame.document());
2866     String referrer = SecurityPolicy::generateReferrerHeader(m_frame.document()->referrerPolicy(), request.url(), outgoingReferrer());
2867     
2868     ResourceRequest initialRequest = request;
2869     initialRequest.setTimeoutInterval(10);
2870     
2871     if (!referrer.isEmpty())
2872         initialRequest.setHTTPReferrer(referrer);
2873     addHTTPOriginIfNeeded(initialRequest, outgoingOrigin());
2874
2875     initialRequest.setFirstPartyForCookies(m_frame.mainFrame().loader().documentLoader()->request().url());
2876     
2877     addExtraFieldsToSubresourceRequest(initialRequest);
2878
2879     unsigned long identifier = 0;    
2880     ResourceRequest newRequest(initialRequest);
2881     requestFromDelegate(newRequest, identifier, error);
2882
2883 #if ENABLE(CONTENT_EXTENSIONS)
2884     if (error.isNull()) {
2885         if (auto* page = m_frame.page()) {
2886             if (m_documentLoader) {
2887                 auto blockedStatus = page->userContentProvider().processContentExtensionRulesForLoad(newRequest.url(), ResourceType::Raw, *m_documentLoader);
2888                 applyBlockedStatusToRequest(blockedStatus, page, newRequest);
2889                 if (blockedStatus.blockedLoad) {
2890                     newRequest = { };
2891                     error = ResourceError(errorDomainWebKitInternal, 0, initialRequest.url(), emptyString());
2892                     response = { };
2893                     data = nullptr;
2894                 }
2895             }
2896         }
2897     }
2898 #endif
2899
2900     m_frame.document()->contentSecurityPolicy()->upgradeInsecureRequestIfNeeded(newRequest, ContentSecurityPolicy::InsecureRequestType::Load);
2901     
2902     if (error.isNull()) {
2903         ASSERT(!newRequest.isNull());
2904
2905         if (!documentLoader()->applicationCacheHost().maybeLoadSynchronously(newRequest, error, response, data)) {
2906             Vector<char> buffer;
2907             platformStrategies()->loaderStrategy()->loadResourceSynchronously(*this, identifier, newRequest, clientCredentialPolicy, options, originalRequestHeaders, error, response, buffer);
2908             data = SharedBuffer::create(WTFMove(buffer));
2909             documentLoader()->applicationCacheHost().maybeLoadFallbackSynchronously(newRequest, error, response, data);
2910             ResourceLoadObserver::shared().logSubresourceLoading(&m_frame, newRequest, response);
2911         }
2912     }
2913     notifier().sendRemainingDelegateMessages(m_documentLoader.get(), identifier, request, response, data ? data->data() : nullptr, data ? data->size() : 0, -1, error);
2914     return identifier;
2915 }
2916
2917 const ResourceRequest& FrameLoader::originalRequest() const
2918 {
2919     return activeDocumentLoader()->originalRequestCopy();
2920 }
2921
2922 void FrameLoader::receivedMainResourceError(const ResourceError& error)
2923 {
2924     // Retain because the stop may release the last reference to it.
2925     Ref<Frame> protect(m_frame);
2926
2927     RefPtr<DocumentLoader> loader = activeDocumentLoader();
2928     // FIXME: Don't want to do this if an entirely new load is going, so should check
2929     // that both data sources on the frame are either this or nil.
2930     stop();
2931     if (m_client.shouldFallBack(error))
2932         handleFallbackContent();
2933
2934     if (m_state == FrameStateProvisional && m_provisionalDocumentLoader) {
2935         if (m_submittedFormURL == m_provisionalDocumentLoader->originalRequestCopy().url())
2936             m_submittedFormURL = URL();
2937             
2938         // We might have made a page cache item, but now we're bailing out due to an error before we ever
2939         // transitioned to the new page (before WebFrameState == commit).  The goal here is to restore any state
2940         // so that the existing view (that wenever got far enough to replace) can continue being used.
2941         history().invalidateCurrentItemCachedPage();
2942         
2943         // Call clientRedirectCancelledOrFinished here so that the frame load delegate is notified that the redirect's
2944         // status has changed, if there was a redirect. The frame load delegate may have saved some state about
2945         // the redirect in its -webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:. Since we are definitely
2946         // not going to use this provisional resource, as it was cancelled, notify the frame load delegate that the redirect
2947         // has ended.
2948         if (m_sentRedirectNotification)
2949             clientRedirectCancelledOrFinished(false);
2950     }
2951
2952     checkCompleted();
2953     if (m_frame.page())
2954         checkLoadComplete();
2955 }
2956
2957 void FrameLoader::continueFragmentScrollAfterNavigationPolicy(const ResourceRequest& request, bool shouldContinue)
2958 {
2959     m_quickRedirectComing = false;
2960
2961     if (!shouldContinue)
2962         return;
2963
2964     // Calling stopLoading() on the provisional document loader can cause the underlying
2965     // frame to be deallocated.
2966     Ref<Frame> protectedFrame(m_frame);
2967
2968     // If we have a provisional request for a different document, a fragment scroll should cancel it.
2969     if (m_provisionalDocumentLoader && !equalIgnoringFragmentIdentifier(m_provisionalDocumentLoader->request().url(), request.url())) {
2970         m_provisionalDocumentLoader->stopLoading();
2971         setProvisionalDocumentLoader(nullptr);
2972     }
2973
2974     bool isRedirect = m_quickRedirectComing || policyChecker().loadType() == FrameLoadType::RedirectWithLockedBackForwardList;
2975     loadInSameDocument(request.url(), 0, !isRedirect);
2976 }
2977
2978 bool FrameLoader::shouldPerformFragmentNavigation(bool isFormSubmission, const String& httpMethod, FrameLoadType loadType, const URL& url)
2979 {
2980     // We don't do this if we are submitting a form with method other than "GET", explicitly reloading,
2981     // currently displaying a frameset, or if the URL does not have a fragment.
2982     // These rules were originally based on what KHTML was doing in KHTMLPart::openURL.
2983
2984     // FIXME: What about load types other than Standard and Reload?
2985
2986     return (!isFormSubmission || equalLettersIgnoringASCIICase(httpMethod, "get"))
2987         && !isReload(loadType)
2988         && loadType != FrameLoadType::Same
2989         && !shouldReload(m_frame.document()->url(), url)
2990         // We don't want to just scroll if a link from within a
2991         // frameset is trying to reload the frameset into _top.
2992         && !m_frame.document()->isFrameSet();
2993 }
2994
2995 static bool itemAllowsScrollRestoration(HistoryItem* historyItem)
2996 {
2997     return !historyItem || historyItem->shouldRestoreScrollPosition();
2998 }
2999
3000 static bool isSameDocumentReload(bool isNewNavigation, FrameLoadType loadType)
3001 {
3002     return !isNewNavigation && !isBackForwardLoadType(loadType);
3003 }
3004
3005 void FrameLoader::scrollToFragmentWithParentBoundary(const URL& url, bool isNewNavigation)
3006 {
3007     FrameView* view = m_frame.view();
3008     if (!view)
3009         return;
3010
3011     // Leaking scroll position to a cross-origin ancestor would permit the so-called "framesniffing" attack.
3012     RefPtr<Frame> boundaryFrame(url.hasFragmentIdentifier() ? m_frame.document()->findUnsafeParentScrollPropagationBoundary() : 0);
3013
3014     if (boundaryFrame)
3015         boundaryFrame->view()->setSafeToPropagateScrollToParent(false);
3016
3017     if (isSameDocumentReload(isNewNavigation, m_loadType) || itemAllowsScrollRestoration(history().currentItem()))
3018         view->scrollToFragment(url);
3019
3020     if (boundaryFrame)
3021         boundaryFrame->view()->setSafeToPropagateScrollToParent(true);
3022 }
3023
3024 bool FrameLoader::shouldClose()
3025 {
3026     Page* page = m_frame.page();
3027     if (!page)
3028         return true;
3029     if (!page->chrome().canRunBeforeUnloadConfirmPanel())
3030         return true;
3031
3032     // Store all references to each subframe in advance since beforeunload's event handler may modify frame
3033     Vector<Ref<Frame>, 16> targetFrames;
3034     targetFrames.append(m_frame);
3035     for (Frame* child = m_frame.tree().firstChild(); child; child = child->tree().traverseNext(&m_frame))
3036         targetFrames.append(*child);
3037
3038     bool shouldClose = false;
3039     {
3040         NavigationDisabler navigationDisabler(&m_frame);
3041         size_t i;
3042
3043         for (i = 0; i < targetFrames.size(); i++) {
3044             if (!targetFrames[i]->tree().isDescendantOf(&m_frame))
3045                 continue;
3046             if (!targetFrames[i]->loader().dispatchBeforeUnloadEvent(page->chrome(), this))
3047                 break;
3048         }
3049
3050         if (i == targetFrames.size())
3051             shouldClose = true;
3052     }
3053
3054     if (!shouldClose)
3055         m_submittedFormURL = URL();
3056
3057     m_currentNavigationHasShownBeforeUnloadConfirmPanel = false;
3058     return shouldClose;
3059 }
3060
3061 void FrameLoader::dispatchUnloadEvents(UnloadEventPolicy unloadEventPolicy)
3062 {
3063     if (!m_frame.document())
3064         return;
3065
3066     // We store the frame's page in a local variable because the frame might get detached inside dispatchEvent.
3067     ForbidPromptsScope forbidPrompts(m_frame.page());
3068     IgnoreOpensDuringUnloadCountIncrementer ignoreOpensDuringUnloadCountIncrementer(m_frame.document());
3069
3070     if (m_didCallImplicitClose && !m_wasUnloadEventEmitted) {
3071         auto* currentFocusedElement = m_frame.document()->focusedElement();
3072         if (is<HTMLInputElement>(currentFocusedElement))
3073             downcast<HTMLInputElement>(*currentFocusedElement).endEditing();
3074         if (m_pageDismissalEventBeingDispatched == PageDismissalType::None) {
3075             if (unloadEventPolicy == UnloadEventPolicyUnloadAndPageHide) {
3076                 m_pageDismissalEventBeingDispatched = PageDismissalType::PageHide;
3077                 m_frame.document()->domWindow()->dispatchEvent(PageTransitionEvent::create(eventNames().pagehideEvent, m_frame.document()->pageCacheState() == Document::AboutToEnterPageCache), m_frame.document());
3078             }
3079
3080             // FIXME: update Page Visibility state here.
3081             // https://bugs.webkit.org/show_bug.cgi?id=116770
3082
3083             if (m_frame.document()->pageCacheState() == Document::NotInPageCache) {
3084                 Ref<Event> unloadEvent(Event::create(eventNames().unloadEvent, false, false));
3085                 // The DocumentLoader (and thus its LoadTiming) might get destroyed
3086                 // while dispatching the event, so protect it to prevent writing the end
3087                 // time into freed memory.
3088                 RefPtr<DocumentLoader> documentLoader = m_provisionalDocumentLoader;
3089                 m_pageDismissalEventBeingDispatched = PageDismissalType::Unload;
3090                 if (documentLoader && documentLoader->timing().startTime() && !documentLoader->timing().unloadEventStart() && !documentLoader->timing().unloadEventEnd()) {
3091                     auto& timing = documentLoader->timing();
3092                     timing.markUnloadEventStart();
3093                     m_frame.document()->domWindow()->dispatchEvent(unloadEvent, m_frame.document());
3094                     timing.markUnloadEventEnd();
3095                 } else
3096                     m_frame.document()->domWindow()->dispatchEvent(unloadEvent, m_frame.document());
3097             }
3098         }
3099         m_pageDismissalEventBeingDispatched = PageDismissalType::None;
3100         m_wasUnloadEventEmitted = true;
3101     }
3102
3103     // Dispatching the unload event could have made m_frame.document() null.
3104     if (!m_frame.document())
3105         return;
3106
3107     if (m_frame.document()->pageCacheState() != Document::NotInPageCache)
3108         return;
3109
3110     // Don't remove event listeners from a transitional empty document (see bug 28716 for more information).
3111     bool keepEventListeners = m_stateMachine.isDisplayingInitialEmptyDocument() && m_provisionalDocumentLoader
3112         && m_frame.document()->isSecureTransitionTo(m_provisionalDocumentLoader->url());
3113
3114     if (!keepEventListeners)
3115         m_frame.document()->removeAllEventListeners();
3116 }
3117
3118 static bool shouldAskForNavigationConfirmation(Document& document, const BeforeUnloadEvent& event)
3119 {
3120     // Confirmation dialog should not be displayed when the allow-modals flag is not set.
3121     if (document.isSandboxed(SandboxModals))
3122         return false;
3123
3124     bool userDidInteractWithPage = document.topDocument().userDidInteractWithPage();
3125     // Web pages can request we ask for confirmation before navigating by:
3126     // - Cancelling the BeforeUnloadEvent (modern way)
3127     // - Setting the returnValue attribute on the BeforeUnloadEvent to a non-empty string.
3128     // - Returning a non-empty string from the event handler, which is then set as returnValue
3129     //   attribute on the BeforeUnloadEvent.
3130     return userDidInteractWithPage && (event.defaultPrevented() || !event.returnValue().isEmpty());
3131 }
3132
3133 bool FrameLoader::dispatchBeforeUnloadEvent(Chrome& chrome, FrameLoader* frameLoaderBeingNavigated)
3134 {
3135     DOMWindow* domWindow = m_frame.document()->domWindow();
3136     if (!domWindow)
3137         return true;
3138
3139     RefPtr<Document> document = m_frame.document();
3140     if (!document->bodyOrFrameset())
3141         return true;
3142     
3143     Ref<BeforeUnloadEvent> beforeUnloadEvent = BeforeUnloadEvent::create();
3144     m_pageDismissalEventBeingDispatched = PageDismissalType::BeforeUnload;
3145
3146     {
3147         ForbidPromptsScope forbidPrompts(m_frame.page());
3148         IgnoreOpensDuringUnloadCountIncrementer ignoreOpensDuringUnloadCountIncrementer(m_frame.document());
3149         domWindow->dispatchEvent(beforeUnloadEvent, domWindow->document());
3150     }
3151
3152     m_pageDismissalEventBeingDispatched = PageDismissalType::None;
3153
3154     if (!beforeUnloadEvent->defaultPrevented())
3155         document->defaultEventHandler(beforeUnloadEvent.get());
3156
3157     if (!shouldAskForNavigationConfirmation(*document, beforeUnloadEvent))
3158         return true;
3159
3160     // If the navigating FrameLoader has already shown a beforeunload confirmation panel for the current navigation attempt,
3161     // this frame is not allowed to cause another one to be shown.
3162     if (frameLoaderBeingNavigated->m_currentNavigationHasShownBeforeUnloadConfirmPanel) {
3163         document->addConsoleMessage(MessageSource::JS, MessageLevel::Error, ASCIILiteral("Blocked attempt to show multiple beforeunload confirmation dialogs for the same navigation."));
3164         return true;
3165     }
3166
3167     // We should only display the beforeunload dialog for an iframe if its SecurityOrigin matches all
3168     // ancestor frame SecurityOrigins up through the navigating FrameLoader.
3169     if (frameLoaderBeingNavigated != this) {
3170         Frame* parentFrame = m_frame.tree().parent();
3171         while (parentFrame) {
3172             Document* parentDocument = parentFrame->document();
3173             if (!parentDocument)
3174                 return true;
3175             if (!m_frame.document() || !m_frame.document()->securityOrigin().canAccess(parentDocument->securityOrigin())) {
3176                 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."));
3177                 return true;
3178             }
3179             
3180             if (&parentFrame->loader() == frameLoaderBeingNavigated)
3181                 break;
3182             
3183             parentFrame = parentFrame->tree().parent();
3184         }
3185         
3186         // The navigatingFrameLoader should always be in our ancestory.
3187         ASSERT(parentFrame);
3188         ASSERT(&parentFrame->loader() == frameLoaderBeingNavigated);
3189     }
3190
3191     frameLoaderBeingNavigated->m_currentNavigationHasShownBeforeUnloadConfirmPanel = true;
3192
3193     String text = document->displayStringModifiedByEncoding(beforeUnloadEvent->returnValue());
3194     return chrome.runBeforeUnloadConfirmPanel(text, m_frame);
3195 }
3196
3197 void FrameLoader::continueLoadAfterNavigationPolicy(const ResourceRequest& request, FormState* formState, ShouldContinue shouldContinue, AllowNavigationToInvalidURL allowNavigationToInvalidURL)
3198 {
3199     // If we loaded an alternate page to replace an unreachableURL, we'll get in here with a
3200     // nil policyDataSource because loading the alternate page will have passed
3201     // through this method already, nested; otherwise, policyDataSource should still be set.
3202     ASSERT(m_policyDocumentLoader || !m_provisionalDocumentLoader->unreachableURL().isEmpty());
3203
3204     bool isTargetItem = history().provisionalItem() ? history().provisionalItem()->isTargetItem() : false;
3205
3206     bool urlIsDisallowed = allowNavigationToInvalidURL == AllowNavigationToInvalidURL::No && !request.url().isValid();
3207     bool canContinue = shouldContinue != ShouldContinue::No && shouldClose() && !urlIsDisallowed;
3208
3209     if (!canContinue) {
3210         // If we were waiting for a quick redirect, but the policy delegate decided to ignore it, then we 
3211         // need to report that the client redirect was cancelled.
3212         // FIXME: The client should be told about ignored non-quick redirects, too.
3213         if (m_quickRedirectComing)
3214             clientRedirectCancelledOrFinished(false);
3215
3216         setPolicyDocumentLoader(nullptr);
3217         checkCompleted();
3218         checkLoadComplete();
3219
3220         // If the navigation request came from the back/forward menu, and we punt on it, we have the 
3221         // problem that we have optimistically moved the b/f cursor already, so move it back. For sanity,
3222         // we only do this when punting a navigation for the target frame or top-level frame.  
3223         if ((isTargetItem || m_frame.isMainFrame()) && isBackForwardLoadType(policyChecker().loadType())) {
3224             if (Page* page = m_frame.page()) {
3225                 if (HistoryItem* resetItem = m_frame.mainFrame().loader().history().currentItem()) {
3226                     page->backForward().setCurrentItem(resetItem);
3227                     m_frame.loader().client().updateGlobalHistoryItemForPage();
3228                 }
3229             }
3230         }
3231         return;
3232     }
3233
3234     FrameLoadType type = policyChecker().loadType();
3235     // A new navigation is in progress, so don't clear the history's provisional item.
3236     stopAllLoaders(ShouldNotClearProvisionalItem);
3237     
3238     // <rdar://problem/6250856> - In certain circumstances on pages with multiple frames, stopAllLoaders()
3239     // might detach the current FrameLoader, in which case we should bail on this newly defunct load. 
3240     if (!m_frame.page())
3241         return;
3242
3243     setProvisionalDocumentLoader(m_policyDocumentLoader.get());
3244     m_loadType = type;
3245     setState(FrameStateProvisional);
3246
3247     setPolicyDocumentLoader(nullptr);
3248
3249     if (isBackForwardLoadType(type)) {
3250         auto& diagnosticLoggingClient = m_frame.page()->diagnosticLoggingClient();
3251         if (history().provisionalItem()->isInPageCache()) {
3252             diagnosticLoggingClient.logDiagnosticMessageWithResult(DiagnosticLoggingKeys::pageCacheKey(), DiagnosticLoggingKeys::retrievalKey(), DiagnosticLoggingResultPass, ShouldSample::Yes);
3253             loadProvisionalItemFromCachedPage();
3254             return;
3255         }
3256         diagnosticLoggingClient.logDiagnosticMessageWithResult(DiagnosticLoggingKeys::pageCacheKey(), DiagnosticLoggingKeys::retrievalKey(), DiagnosticLoggingResultFail, ShouldSample::Yes);
3257     }
3258
3259     CompletionHandler<void(void)> completionHandler = [this, shouldContinue] {
3260         if (!m_provisionalDocumentLoader)
3261             return;
3262         
3263         prepareForLoadStart();
3264         
3265         // The load might be cancelled inside of prepareForLoadStart(), nulling out the m_provisionalDocumentLoader,
3266         // so we need to null check it again.
3267         if (!m_provisionalDocumentLoader) {
3268             RELEASE_LOG_IF_ALLOWED("dispatchWillSubmitForm completionHandler: Frame load canceled (frame = %p, main = %d)", &m_frame, m_frame.isMainFrame());
3269             return;
3270         }
3271         
3272         DocumentLoader* activeDocLoader = activeDocumentLoader();
3273         if (activeDocLoader && activeDocLoader->isLoadingMainResource()) {
3274             RELEASE_LOG_IF_ALLOWED("dispatchWillSubmitForm completionHandler: Main frame already being loaded (frame = %p, main = %d)", &m_frame, m_frame.isMainFrame());
3275             return;
3276         }
3277         
3278         m_loadingFromCachedPage = false;
3279
3280         // We handle suspension by navigating forward to about:blank, which leaves us setup to navigate back to resume.
3281         if (shouldContinue == ShouldContinue::ForSuspension)
3282             m_provisionalDocumentLoader->willContinueMainResourceLoadAfterRedirect({ blankURL() });
3283
3284         m_provisionalDocumentLoader->startLoadingMainResource(shouldContinue);
3285     };
3286     
3287     if (!formState) {
3288         completionHandler();
3289         return;
3290     }
3291
3292     m_client.dispatchWillSubmitForm(*formState, WTFMove(completionHandler));
3293 }
3294
3295 void FrameLoader::continueLoadAfterNewWindowPolicy(const ResourceRequest& request,
3296     FormState* formState, const String& frameName, const NavigationAction& action, ShouldContinue shouldContinue, AllowNavigationToInvalidURL allowNavigationToInvalidURL, NewFrameOpenerPolicy openerPolicy)
3297 {
3298     ASSERT(shouldContinue != ShouldContinue::ForSuspension);
3299     if (shouldContinue != ShouldContinue::Yes)
3300         return;
3301
3302     Ref<Frame> frame(m_frame);
3303     RefPtr<Frame> mainFrame = m_client.dispatchCreatePage(action);
3304     if (!mainFrame)
3305         return;
3306
3307     SandboxFlags sandboxFlags = frame->loader().effectiveSandboxFlags();
3308     if (sandboxFlags & SandboxPropagatesToAuxiliaryBrowsingContexts)
3309         mainFrame->loader().forceSandboxFlags(sandboxFlags);
3310
3311     if (!equalIgnoringASCIICase(frameName, "_blank"))
3312         mainFrame->tree().setName(frameName);
3313
3314     mainFrame->page()->setOpenedByDOM();
3315     mainFrame->loader().m_client.dispatchShow();
3316     if (openerPolicy == NewFrameOpenerPolicy::Allow) {
3317         mainFrame->loader().setOpener(frame.ptr());
3318         mainFrame->document()->setReferrerPolicy(frame->document()->referrerPolicy());
3319     }
3320
3321     NavigationAction newAction { *frame->document(), request, InitiatedByMainFrame::Unknown, NavigationType::Other, action.shouldOpenExternalURLsPolicy() };
3322     mainFrame->loader().loadWithNavigationAction(request, newAction, LockHistory::No, FrameLoadType::Standard, formState, allowNavigationToInvalidURL, [] { });
3323 }
3324
3325 void FrameLoader::requestFromDelegate(ResourceRequest& request, unsigned long& identifier, ResourceError& error)
3326 {
3327     ASSERT(!request.isNull());
3328
3329     identifier = 0;
3330     if (Page* page = m_frame.page()) {
3331         identifier = page->progress().createUniqueIdentifier();
3332         notifier().assignIdentifierToInitialRequest(identifier, m_documentLoader.get(), request);
3333     }
3334
3335     ResourceRequest newRequest(request);
3336     notifier().dispatchWillSendRequest(m_documentLoader.get(), identifier, newRequest, ResourceResponse());
3337
3338     if (newRequest.isNull())
3339         error = cancelledError(request);
3340     else
3341         error = ResourceError();
3342
3343     request = newRequest;
3344 }
3345
3346 void FrameLoader::loadedResourceFromMemoryCache(CachedResource& resource, ResourceRequest& newRequest, ResourceError& error)
3347 {
3348     Page* page = m_frame.page();
3349     if (!page)
3350         return;
3351
3352     if (!resource.shouldSendResourceLoadCallbacks() || m_documentLoader->haveToldClientAboutLoad(resource.url()))
3353         return;
3354
3355     // Main resource delegate messages are synthesized in MainResourceLoader, so we must not send them here.
3356     if (resource.type() == CachedResource::MainResource)
3357         return;
3358
3359     if (!page->areMemoryCacheClientCallsEnabled()) {
3360         InspectorInstrumentation::didLoadResourceFromMemoryCache(*page, m_documentLoader.get(), &resource);
3361         m_documentLoader->recordMemoryCacheLoadForFutureClientNotification(resource.resourceRequest());
3362         m_documentLoader->didTellClientAboutLoad(resource.url());
3363         return;
3364     }
3365
3366     if (m_client.dispatchDidLoadResourceFromMemoryCache(m_documentLoader.get(), newRequest, resource.response(), resource.encodedSize())) {
3367         InspectorInstrumentation::didLoadResourceFromMemoryCache(*page, m_documentLoader.get(), &resource);
3368         m_documentLoader->didTellClientAboutLoad(resource.url());
3369         return;
3370     }
3371
3372     unsigned long identifier;
3373     requestFromDelegate(newRequest, identifier, error);
3374
3375     ResourceResponse response = resource.response();
3376     response.setSource(ResourceResponse::Source::MemoryCache);
3377     notifier().sendRemainingDelegateMessages(m_documentLoader.get(), identifier, newRequest, response, 0, resource.encodedSize(), 0, error);
3378 }
3379
3380 void FrameLoader::applyUserAgentIfNeeded(ResourceRequest& request)
3381 {
3382     if (!request.hasHTTPHeaderField(HTTPHeaderName::UserAgent)) {
3383         String userAgent = this->userAgent(request.url());
3384         ASSERT(!userAgent.isNull());
3385         request.setHTTPUserAgent(userAgent);
3386     }
3387 }
3388
3389 bool FrameLoader::shouldInterruptLoadForXFrameOptions(const String& content, const URL& url, unsigned long requestIdentifier)
3390 {
3391     Frame& topFrame = m_frame.tree().top();
3392     if (&m_frame == &topFrame)
3393         return false;
3394
3395     XFrameOptionsDisposition disposition = parseXFrameOptionsHeader(content);
3396
3397     switch (disposition) {
3398     case XFrameOptionsSameOrigin: {
3399         RefPtr<SecurityOrigin> origin = SecurityOrigin::create(url);
3400         if (!origin->isSameSchemeHostPort(topFrame.document()->securityOrigin()))
3401             return true;
3402         for (Frame* frame = m_frame.tree().parent(); frame; frame = frame->tree().parent()) {
3403             if (!origin->isSameSchemeHostPort(frame->document()->securityOrigin()))
3404                 break;
3405         }
3406         return false;
3407     }
3408     case XFrameOptionsDeny:
3409         return true;
3410     case XFrameOptionsAllowAll:
3411         return false;
3412     case XFrameOptionsConflict:
3413         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);
3414         return true;
3415     case XFrameOptionsInvalid:
3416         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);
3417         return false;
3418     case XFrameOptionsNone:
3419         return false;
3420     }
3421     ASSERT_NOT_REACHED();
3422     return false;
3423 }
3424
3425 void FrameLoader::loadProvisionalItemFromCachedPage()
3426 {
3427     DocumentLoader* provisionalLoader = provisionalDocumentLoader();
3428     LOG(PageCache, "WebCorePageCache: Loading provisional DocumentLoader %p with URL '%s' from CachedPage", provisionalDocumentLoader(), provisionalDocumentLoader()->url().stringCenterEllipsizedToLength().utf8().data());
3429
3430     prepareForLoadStart();
3431
3432     m_loadingFromCachedPage = true;
3433
3434     // Should have timing data from previous time(s) the page was shown.
3435     ASSERT(provisionalLoader->timing().startTime());
3436     provisionalLoader->resetTiming();
3437     provisionalLoader->timing().markStartTime();
3438
3439     provisionalLoader->setCommitted(true);
3440     commitProvisionalLoad();
3441 }
3442
3443 bool FrameLoader::shouldTreatURLAsSameAsCurrent(const URL& url) const
3444 {
3445     if (!history().currentItem())
3446         return false;
3447     return url == history().currentItem()->url() || url == history().currentItem()->originalURL();
3448 }
3449
3450 bool FrameLoader::shouldTreatURLAsSrcdocDocument(const URL& url) const
3451 {
3452     if (!equalLettersIgnoringASCIICase(url.string(), "about:srcdoc"))
3453         return false;
3454     HTMLFrameOwnerElement* ownerElement = m_frame.ownerElement();
3455     if (!ownerElement)
3456         return false;
3457     if (!ownerElement->hasTagName(iframeTag))
3458         return false;
3459     return ownerElement->hasAttributeWithoutSynchronization(srcdocAttr);
3460 }
3461
3462 Frame* FrameLoader::findFrameForNavigation(const AtomicString& name, Document* activeDocument)
3463 {
3464     Frame* frame = m_frame.tree().find(name);
3465
3466     // FIXME: Eventually all callers should supply the actual activeDocument so we can call canNavigate with the right document.
3467     if (!activeDocument)
3468         activeDocument = m_frame.document();
3469
3470     if (!activeDocument->canNavigate(frame))
3471         return nullptr;
3472
3473     return frame;
3474 }
3475
3476 void FrameLoader::loadSameDocumentItem(HistoryItem& item)
3477 {
3478     ASSERT(item.documentSequenceNumber() == history().currentItem()->documentSequenceNumber());
3479
3480     Ref<Frame> protect(m_frame);
3481
3482     // Save user view state to the current history item here since we don't do a normal load.
3483     // FIXME: Does form state need to be saved here too?
3484     history().saveScrollPositionAndViewStateToItem(history().currentItem());
3485     if (FrameView* view = m_frame.view())
3486         view->setWasScrolledByUser(false);
3487
3488     history().setCurrentItem(&item);
3489         
3490     // loadInSameDocument() actually changes the URL and notifies load delegates of a "fake" load
3491     loadInSameDocument(item.url(), item.stateObject(), false);
3492
3493     // Restore user view state from the current history item here since we don't do a normal load.
3494     history().restoreScrollPositionAndViewState();
3495 }
3496
3497 // FIXME: This function should really be split into a couple pieces, some of
3498 // which should be methods of HistoryController and some of which should be
3499 // methods of FrameLoader.
3500 void FrameLoader::loadDifferentDocumentItem(HistoryItem& item, FrameLoadType loadType, FormSubmissionCacheLoadPolicy cacheLoadPolicy, NavigationPolicyCheck navigationPolicyCheck)
3501 {
3502     // Remember this item so we can traverse any child items as child frames load
3503     history().setProvisionalItem(&item);
3504
3505     auto initiatedByMainFrame = InitiatedByMainFrame::Unknown;
3506
3507     SetForScope<bool> currentLoadShouldCheckNavigationPolicyGuard(m_currentLoadShouldCheckNavigationPolicy, navigationPolicyCheck != NavigationPolicyCheck::Bypass);
3508
3509     if (CachedPage* cachedPage = PageCache::singleton().get(item, m_frame.page())) {
3510         auto documentLoader = cachedPage->documentLoader();
3511         m_client.updateCachedDocumentLoader(*documentLoader);
3512         documentLoader->setTriggeringAction({ *m_frame.document(), documentLoader->request(), initiatedByMainFrame, loadType, false });
3513         documentLoader->setLastCheckedRequest(ResourceRequest());
3514         loadWithDocumentLoader(documentLoader, loadType, 0, AllowNavigationToInvalidURL::Yes, navigationPolicyCheck, [] { });
3515         return;
3516     }
3517
3518     URL itemURL = item.url();
3519     URL itemOriginalURL = item.originalURL();
3520     URL currentURL;
3521     if (documentLoader())
3522         currentURL = documentLoader()->url();
3523     RefPtr<FormData> formData = item.formData();
3524
3525     ResourceRequest request(itemURL);
3526
3527     if (!item.referrer().isNull())
3528         request.setHTTPReferrer(item.referrer());
3529
3530     ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy = shouldOpenExternalURLsPolicyToApply(m_frame, initiatedByMainFrame, item.shouldOpenExternalURLsPolicy());
3531     bool isFormSubmission = false;
3532     Event* event = nullptr;
3533
3534     // If this was a repost that failed the page cache, we might try to repost the form.
3535     NavigationAction action;
3536     if (formData) {
3537         formData->generateFiles(m_frame.document());
3538
3539         request.setHTTPMethod("POST");
3540         request.setHTTPBody(WTFMove(formData));
3541         request.setHTTPContentType(item.formContentType());
3542         RefPtr<SecurityOrigin> securityOrigin = SecurityOrigin::createFromString(item.referrer());
3543         addHTTPOriginIfNeeded(request, securityOrigin->toString());
3544         addHTTPUpgradeInsecureRequestsIfNeeded(request);
3545
3546         // Make sure to add extra fields to the request after the Origin header is added for the FormData case.
3547         // See https://bugs.webkit.org/show_bug.cgi?id=22194 for more discussion.
3548         addExtraFieldsToRequest(request, loadType, true);
3549         
3550         // FIXME: Slight hack to test if the NSURL cache contains the page we're going to.
3551         // We want to know this before talking to the policy delegate, since it affects whether 
3552         // we show the DoYouReallyWantToRepost nag.
3553         //
3554         // This trick has a small bug (3123893) where we might find a cache hit, but then
3555         // have the item vanish when we try to use it in the ensuing nav.  This should be
3556         // extremely rare, but in that case the user will get an error on the navigation.
3557         
3558         if (cacheLoadPolicy == MayAttemptCacheOnlyLoadForFormSubmissionItem) {
3559             request.setCachePolicy(ReturnCacheDataDontLoad);
3560             action = { *m_frame.document(), request, initiatedByMainFrame, loadType, isFormSubmission, event, shouldOpenExternalURLsPolicy };
3561         } else {
3562             request.setCachePolicy(ReturnCacheDataElseLoad);
3563             action = { *m_frame.document(), request, initiatedByMainFrame, NavigationType::FormResubmitted, shouldOpenExternalURLsPolicy, event };
3564         }
3565     } else {
3566         switch (loadType) {
3567         case FrameLoadType::Reload:
3568         case FrameLoadType::ReloadFromOrigin:
3569         case FrameLoadType::ReloadExpiredOnly:
3570             request.setCachePolicy(ReloadIgnoringCacheData);
3571             break;
3572         case FrameLoadType::Back:
3573         case FrameLoadType::Forward:
3574         case FrameLoadType::IndexedBackForward: {
3575 #if PLATFORM(COCOA)
3576             bool allowStaleData = true;
3577 #else
3578             bool allowStaleData = !item.wasRestoredFromSession();
3579 #endif
3580             if (allowStaleData)
3581                 request.setCachePolicy(ReturnCacheDataElseLoad);
3582             item.setWasRestoredFromSession(false);
3583             break;
3584         }
3585         case FrameLoadType::Standard:
3586         case FrameLoadType::RedirectWithLockedBackForwardList:
3587             break;
3588         case FrameLoadType::Same:
3589         case FrameLoadType::Replace:
3590             ASSERT_NOT_REACHED();
3591         }
3592
3593         addExtraFieldsToRequest(request, loadType, true);
3594
3595         ResourceRequest requestForOriginalURL(request);
3596         requestForOriginalURL.setURL(itemOriginalURL);
3597         action = { *m_frame.document(), requestForOriginalURL, initiatedByMainFrame, loadType, isFormSubmission, event, shouldOpenExternalURLsPolicy };
3598     }
3599
3600     loadWithNavigationAction(request, action, LockHistory::No, loadType, 0, AllowNavigationToInvalidURL::Yes, [] { });
3601 }
3602
3603 // Loads content into this frame, as specified by history item
3604 void FrameLoader::loadItem(HistoryItem& item, FrameLoadType loadType, NavigationPolicyCheck navigationPolicyCheck)
3605 {
3606     m_requestedHistoryItem = &item;
3607     HistoryItem* currentItem = history().currentItem();
3608     bool sameDocumentNavigation = currentItem && item.shouldDoSameDocumentNavigationTo(*currentItem);
3609
3610     if (sameDocumentNavigation)
3611         loadSameDocumentItem(item);
3612     else
3613         loadDifferentDocumentItem(item, loadType, MayAttemptCacheOnlyLoadForFormSubmissionItem, navigationPolicyCheck);
3614 }
3615
3616 void FrameLoader::retryAfterFailedCacheOnlyMainResourceLoad()
3617 {
3618     ASSERT(m_state == FrameStateProvisional);
3619     ASSERT(!m_loadingFromCachedPage);
3620     ASSERT(history().provisionalItem());
3621     ASSERT(history().provisionalItem()->formData());
3622     ASSERT(history().provisionalItem() == m_requestedHistoryItem.get());
3623
3624     FrameLoadType loadType = m_loadType;
3625     HistoryItem& item = *history().provisionalItem();
3626
3627     stopAllLoaders(ShouldNotClearProvisionalItem);
3628     loadDifferentDocumentItem(item, loadType, MayNotAttemptCacheOnlyLoadForFormSubmissionItem, NavigationPolicyCheck::Require);
3629 }
3630
3631 ResourceError FrameLoader::cancelledError(const ResourceRequest& request) const
3632 {
3633     ResourceError error = m_client.cancelledError(request);
3634     error.setType(ResourceError::Type::Cancellation);
3635     return error;
3636 }
3637
3638 ResourceError FrameLoader::blockedByContentBlockerError(const ResourceRequest& request) const
3639 {
3640     return m_client.blockedByContentBlockerError(request);
3641 }
3642
3643 ResourceError FrameLoader::blockedError(const ResourceRequest& request) const
3644 {
3645     ResourceError error = m_client.blockedError(request);
3646     error.setType(ResourceError::Type::Cancellation);
3647     return error;
3648 }
3649
3650 #if ENABLE(CONTENT_FILTERING)
3651 ResourceError FrameLoader::blockedByContentFilterError(const ResourceRequest& request) const
3652 {
3653     ResourceError error = m_client.blockedByContentFilterError(request);
3654     error.setType(ResourceError::Type::General);
3655     return error;
3656 }
3657 #endif
3658
3659 #if PLATFORM(IOS)
3660 RetainPtr<CFDictionaryRef> FrameLoader::connectionProperties(ResourceLoader* loader)
3661 {
3662     return m_client.connectionProperties(loader->documentLoader(), loader->identifier());
3663 }
3664 #endif
3665
3666 ReferrerPolicy FrameLoader::effectiveReferrerPolicy() const
3667 {
3668     if (auto* parentFrame = m_frame.tree().parent())
3669         return parentFrame->document()->referrerPolicy();
3670     if (m_opener)
3671         return m_opener->document()->referrerPolicy();
3672     return ReferrerPolicy::NoReferrerWhenDowngrade;
3673 }
3674
3675 String FrameLoader::referrer() const
3676 {
3677     return m_documentLoader ? m_documentLoader->request().httpReferrer() : emptyString();
3678 }
3679
3680 void FrameLoader::dispatchDidClearWindowObjectsInAllWorlds()
3681 {
3682     if (!m_frame.script().canExecuteScripts(NotAboutToExecuteScript))
3683         return;
3684
3685     Vector<Ref<DOMWrapperWorld>> worlds;
3686     ScriptController::getAllWorlds(worlds);
3687     for (auto& world : worlds)
3688         dispatchDidClearWindowObjectInWorld(world);
3689 }
3690
3691 void FrameLoader::dispatchDidClearWindowObjectInWorld(DOMWrapperWorld& world)
3692 {
3693     if (!m_frame.script().canExecuteScripts(NotAboutToExecuteScript) || !m_frame.windowProxy().existingJSWindowProxy(world))
3694         return;
3695
3696     m_client.dispatchDidClearWindowObjectInWorld(world);
3697
3698     if (Page* page = m_frame.page())
3699         page->inspectorController().didClearWindowObjectInWorld(m_frame, world);
3700
3701     InspectorInstrumentation::didClearWindowObjectInWorld(m_frame, world);
3702 }
3703
3704 void FrameLoader::dispatchGlobalObjectAvailableInAllWorlds()
3705 {
3706     Vector<Ref<DOMWrapperWorld>> worlds;
3707     ScriptController::getAllWorlds(worlds);
3708     for (auto& world : worlds)
3709         m_client.dispatchGlobalObjectAvailable(world);
3710 }
3711
3712 SandboxFlags FrameLoader::effectiveSandboxFlags() const
3713 {
3714     SandboxFlags flags = m_forcedSandboxFlags;
3715     if (Frame* parentFrame = m_frame.tree().parent())
3716         flags |= parentFrame->document()->sandboxFlags();
3717     if (HTMLFrameOwnerElement* ownerElement = m_frame.ownerElement())
3718         flags |= ownerElement->sandboxFlags();
3719     return flags;
3720 }
3721
3722 void FrameLoader::didChangeTitle(DocumentLoader* loader)
3723 {
3724     m_client.didChangeTitle(loader);
3725
3726     if (loader == m_documentLoader) {
3727         // Must update the entries in the back-forward list too.
3728         history().setCurrentItemTitle(loader->title());
3729         // This must go through the WebFrame because it has the right notion of the current b/f item.
3730         m_client.setTitle(loader->title(), loader->urlForHistory());
3731         m_client.setMainFrameDocumentReady(true); // update observers with new DOMDocument
3732         m_client.dispatchDidReceiveTitle(loader->title());
3733     }
3734
3735 #if ENABLE(REMOTE_INSPECTOR)
3736     if (m_frame.isMainFrame())
3737         m_frame.page()->remoteInspectorInformationDidChange();
3738 #endif
3739 }
3740
3741 void FrameLoader::dispatchDidCommitLoad(std::optional<HasInsecureContent> initialHasInsecureContent)
3742 {
3743     if (m_stateMachine.creatingInitialEmptyDocument())
3744         return;
3745
3746     m_client.dispatchDidCommitLoad(initialHasInsecureContent);
3747
3748     if (m_frame.isMainFrame()) {
3749         m_frame.page()->resetSeenPlugins();
3750         m_frame.page()->resetSeenMediaEngines();
3751     }
3752
3753     InspectorInstrumentation::didCommitLoad(m_frame, m_documentLoader.get());
3754
3755 #if ENABLE(REMOTE_INSPECTOR)
3756     if (m_frame.isMainFrame())
3757         m_frame.page()->remoteInspectorInformationDidChange();
3758 #endif
3759 }
3760
3761 void FrameLoader::tellClientAboutPastMemoryCacheLoads()
3762 {
3763     ASSERT(m_frame.page());
3764     ASSERT(m_frame.page()->areMemoryCacheClientCallsEnabled());
3765
3766     if (!m_documentLoader)
3767         return;
3768
3769     Vector<ResourceRequest> pastLoads;
3770     m_documentLoader->takeMemoryCacheLoadsForClientNotification(pastLoads);
3771
3772     for (auto& pastLoad : pastLoads) {
3773         CachedResource* resource = MemoryCache::singleton().resourceForRequest(pastLoad, m_frame.page()->sessionID());
3774
3775         // FIXME: These loads, loaded from cache, but now gone from the cache by the time
3776         // Page::setMemoryCacheClientCallsEnabled(true) is called, will not be seen by the client.
3777         // Consider if there's some efficient way of remembering enough to deliver this client call.
3778         // We have the URL, but not the rest of the response or the length.
3779         if (!resource)
3780             continue;
3781
3782         ResourceRequest request(resource->url());
3783         m_client.dispatchDidLoadResourceFromMemoryCache(m_documentLoader.get(), request, resource->response(), resource->encodedSize());
3784     }
3785 }
3786
3787 NetworkingContext* FrameLoader::networkingContext() const
3788 {
3789     return m_networkingContext.get();
3790 }
3791
3792 void FrameLoader::loadProgressingStatusChanged()
3793 {
3794     if (auto* view = m_frame.mainFrame().view())
3795         view->loadProgressingStatusChanged();
3796 }
3797
3798 void FrameLoader::forcePageTransitionIfNeeded()
3799 {
3800     m_client.forcePageTransitionIfNeeded();
3801 }
3802
3803 void FrameLoader::clearTestingOverrides()
3804 {
3805     m_overrideCachePolicyForTesting = std::nullopt;
3806     m_overrideResourceLoadPriorityForTesting = std::nullopt;
3807     m_isStrictRawResourceValidationPolicyDisabledForTesting = false;
3808 }
3809
3810 bool FrameLoader::isAlwaysOnLoggingAllowed() const
3811 {
3812     return frame().isAlwaysOnLoggingAllowed();
3813 }
3814
3815 bool FrameLoaderClient::hasHTMLView() const
3816 {
3817     return true;
3818 }
3819
3820 RefPtr<Frame> createWindow(Frame& openerFrame, Frame& lookupFrame, FrameLoadRequest&& request, const WindowFeatures& features, bool& created)
3821 {
3822     ASSERT(!features.dialog || request.frameName().isEmpty());
3823
3824     created = false;
3825
3826     // FIXME: Provide line number information with respect to the opener's document.
3827     if (protocolIsJavaScript(request.resourceRequest().url()) && !openerFrame.document()->contentSecurityPolicy()->allowJavaScriptURLs(openerFrame.document()->url(), { }))
3828         return nullptr;
3829
3830     if (!request.frameName().isEmpty() && !equalIgnoringASCIICase(request.frameName(), "_blank")) {
3831         if (RefPtr<Frame> frame = lookupFrame.loader().findFrameForNavigation(request.frameName(), openerFrame.document())) {
3832             if (!equalIgnoringASCIICase(request.frameName(), "_self")) {
3833                 if (Page* page = frame->page())
3834                     page->chrome().focus();
3835             }
3836             return frame;
3837         }
3838     }
3839
3840     // Sandboxed frames cannot open new auxiliary browsing contexts.
3841     if (isDocumentSandboxed(openerFrame, SandboxPopups)) {
3842         // FIXME: This message should be moved off the console once a solution to https://bugs.webkit.org/show_bug.cgi?id=103274 exists.
3843         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.");
3844         return nullptr;
3845     }
3846
3847     // FIXME: Setting the referrer should be the caller's responsibility.
3848     String referrer = SecurityPolicy::generateReferrerHeader(openerFrame.document()->referrerPolicy(), request.resourceRequest().url(), openerFrame.loader().outgoingReferrer());
3849     if (!referrer.isEmpty())
3850         request.resourceRequest().setHTTPReferrer(referrer);
3851     FrameLoader::addHTTPOriginIfNeeded(request.resourceRequest(), openerFrame.loader().outgoingOrigin());
3852     FrameLoader::addHTTPUpgradeInsecureRequestsIfNeeded(request.resourceRequest());
3853     FrameLoader::addSameSiteInfoToRequestIfNeeded(request.resourceRequest(), openerFrame.document());
3854
3855     Page* oldPage = openerFrame.page();
3856     if (!oldPage)
3857         return nullptr;
3858
3859     ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy = shouldOpenExternalURLsPolicyToApply(openerFrame, request);
3860     NavigationAction action { request.requester(), request.resourceRequest(), request.initiatedByMainFrame(), NavigationType::Other, shouldOpenExternalURLsPolicy };
3861     Page* page = oldPage->chrome().createWindow(openerFrame, request, features, action);
3862     if (!page)
3863         return nullptr;
3864
3865     RefPtr<Frame> frame = &page->mainFrame();
3866
3867     if (isDocumentSandboxed(openerFrame, SandboxPropagatesToAuxiliaryBrowsingContexts))
3868         frame->loader().forceSandboxFlags(openerFrame.document()->sandboxFlags());
3869
3870     if (!equalIgnoringASCIICase(request.frameName(), "_blank"))
3871         frame->tree().setName(request.frameName());
3872
3873     page->chrome().setToolbarsVisible(features.toolBarVisible || features.locationBarVisible);
3874
3875     if (!frame->page())
3876         return nullptr;
3877     page->chrome().setStatusbarVisible(features.statusBarVisible);
3878
3879     if (!frame->page())
3880         return nullptr;
3881     page->chrome().setScrollbarsVisible(features.scrollbarsVisible);
3882
3883     if (!frame->page())
3884         return nullptr;
3885     page->chrome().setMenubarVisible(features.menuBarVisible);
3886
3887     if (!frame->page())
3888         return nullptr;
3889     page->chrome().setResizable(features.resizable);
3890
3891     // 'x' and 'y' specify the location of the window, while 'width' and 'height'
3892     // specify the size of the viewport. We can only resize the window, so adjust
3893     // for the difference between the window size and the viewport size.
3894
3895     // FIXME: We should reconcile the initialization of viewport arguments between iOS and non-IOS.
3896 #if !PLATFORM(IOS)
3897     FloatSize viewportSize = page->chrome().pageRect().size();
3898     FloatRect windowRect = page->chrome().windowRect();
3899     if (features.x)
3900         windowRect.setX(*features.x);
3901     if (features.y)
3902         windowRect.setY(*features.y);
3903     // Zero width and height mean using default size, not minumum one.
3904     if (features.width && *features.width)
3905         windowRect.setWidth(*features.width + (windowRect.width() - viewportSize.width()));
3906     if (features.height && *features.height)
3907         windowRect.setHeight(*features.height + (windowRect.height() - viewportSize.height()));
3908
3909     // Ensure non-NaN values, minimum size as well as being within valid screen area.
3910     FloatRect newWindowRect = DOMWindow::adjustWindowRect(*page, windowRect);
3911
3912     if (!frame->page())
3913         return nullptr;
3914     page->chrome().setWindowRect(newWindowRect);
3915 #else
3916     // On iOS, width and height refer to the viewport dimensions.
3917     ViewportArguments arguments;
3918     // Zero width and height mean using default size, not minimum one.
3919     if (features.width && *features.width)
3920         arguments.width = *features.width;
3921     if (features.height && *features.height)
3922         arguments.height = *features.height;
3923     frame->setViewportArguments(arguments);
3924 #endif
3925
3926     if (!frame->page())
3927         return nullptr;
3928     page->chrome().show();
3929
3930     created = true;
3931     return frame;
3932 }
3933
3934 bool FrameLoader::shouldSuppressTextInputFromEditing() const
3935 {
3936     return m_frame.settings().shouldSuppressTextInputFromEditingDuringProvisionalNavigation() && m_state == FrameStateProvisional;
3937 }
3938
3939 } // namespace WebCore