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