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