523b30d95ba070161167b7f144fdfe66605fa54c
[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()->resetUnlessSuspendedForPageCache();
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 const ResourceRequest& FrameLoader::initialRequest() const
1468 {
1469     return activeDocumentLoader()->originalRequest();
1470 }
1471
1472 bool FrameLoader::willLoadMediaElementURL(URL& url)
1473 {
1474 #if PLATFORM(IOS)
1475     // MobileStore depends on the iOS 4.0 era client delegate method because webView:resource:willSendRequest:redirectResponse:fromDataSource
1476     // doesn't let them tell when a load request is coming from a media element. See <rdar://problem/8266916> for more details.
1477     if (applicationIsMobileStore())
1478         return m_client.shouldLoadMediaElementURL(url);
1479 #endif
1480
1481     ResourceRequest request(url);
1482
1483     unsigned long identifier;
1484     ResourceError error;
1485     requestFromDelegate(request, identifier, error);
1486     notifier().sendRemainingDelegateMessages(m_documentLoader.get(), identifier, request, ResourceResponse(url, String(), -1, String()), 0, -1, -1, error);
1487
1488     url = request.url();
1489
1490     return error.isNull();
1491 }
1492
1493 bool FrameLoader::shouldReloadToHandleUnreachableURL(DocumentLoader* docLoader)
1494 {
1495     URL unreachableURL = docLoader->unreachableURL();
1496
1497     if (unreachableURL.isEmpty())
1498         return false;
1499
1500     if (!isBackForwardLoadType(policyChecker().loadType()))
1501         return false;
1502
1503     // We only treat unreachableURLs specially during the delegate callbacks
1504     // for provisional load errors and navigation policy decisions. The former
1505     // case handles well-formed URLs that can't be loaded, and the latter
1506     // case handles malformed URLs and unknown schemes. Loading alternate content
1507     // at other times behaves like a standard load.
1508     if (policyChecker().delegateIsDecidingNavigationPolicy() || policyChecker().delegateIsHandlingUnimplementablePolicy())
1509         return m_policyDocumentLoader && unreachableURL == m_policyDocumentLoader->request().url();
1510
1511     return unreachableURL == m_provisionalLoadErrorBeingHandledURL;
1512 }
1513
1514 void FrameLoader::reloadWithOverrideEncoding(const String& encoding)
1515 {
1516     if (!m_documentLoader)
1517         return;
1518
1519     ResourceRequest request = m_documentLoader->request();
1520     URL unreachableURL = m_documentLoader->unreachableURL();
1521     if (!unreachableURL.isEmpty())
1522         request.setURL(unreachableURL);
1523
1524     // FIXME: If the resource is a result of form submission and is not cached, the form will be silently resubmitted.
1525     // We should ask the user for confirmation in this case.
1526     request.setCachePolicy(ReturnCacheDataElseLoad);
1527
1528     Ref<DocumentLoader> loader = m_client.createDocumentLoader(request, defaultSubstituteDataForURL(request.url()));
1529     applyShouldOpenExternalURLsPolicyToNewDocumentLoader(loader, m_documentLoader->shouldOpenExternalURLsPolicyToPropagate());
1530
1531     setPolicyDocumentLoader(loader.ptr());
1532
1533     loader->setOverrideEncoding(encoding);
1534
1535     loadWithDocumentLoader(loader.ptr(), FrameLoadType::Reload, 0, AllowNavigationToInvalidURL::Yes);
1536 }
1537
1538 void FrameLoader::reload(bool endToEndReload, bool contentBlockersEnabled)
1539 {
1540     if (!m_documentLoader)
1541         return;
1542
1543     // If a window is created by javascript, its main frame can have an empty but non-nil URL.
1544     // Reloading in this case will lose the current contents (see 4151001).
1545     if (m_documentLoader->request().url().isEmpty())
1546         return;
1547
1548     // Replace error-page URL with the URL we were trying to reach.
1549     ResourceRequest initialRequest = m_documentLoader->request();
1550     URL unreachableURL = m_documentLoader->unreachableURL();
1551     if (!unreachableURL.isEmpty())
1552         initialRequest.setURL(unreachableURL);
1553
1554     // Create a new document loader for the reload, this will become m_documentLoader eventually,
1555     // but first it has to be the "policy" document loader, and then the "provisional" document loader.
1556     Ref<DocumentLoader> loader = m_client.createDocumentLoader(initialRequest, defaultSubstituteDataForURL(initialRequest.url()));
1557     applyShouldOpenExternalURLsPolicyToNewDocumentLoader(loader, m_documentLoader->shouldOpenExternalURLsPolicyToPropagate());
1558
1559     loader->setUserContentExtensionsEnabled(contentBlockersEnabled);
1560     
1561     ResourceRequest& request = loader->request();
1562
1563     // FIXME: We don't have a mechanism to revalidate the main resource without reloading at the moment.
1564     request.setCachePolicy(ReloadIgnoringCacheData);
1565
1566     // If we're about to re-post, set up action so the application can warn the user.
1567     if (request.httpMethod() == "POST")
1568         loader->setTriggeringAction(NavigationAction(request, NavigationType::FormResubmitted));
1569
1570     loader->setOverrideEncoding(m_documentLoader->overrideEncoding());
1571     
1572     loadWithDocumentLoader(loader.ptr(), endToEndReload ? FrameLoadType::ReloadFromOrigin : FrameLoadType::Reload, 0, AllowNavigationToInvalidURL::Yes);
1573 }
1574
1575 void FrameLoader::stopAllLoaders(ClearProvisionalItemPolicy clearProvisionalItemPolicy)
1576 {
1577     ASSERT(!m_frame.document() || !m_frame.document()->inPageCache());
1578     if (m_pageDismissalEventBeingDispatched != PageDismissalType::None)
1579         return;
1580
1581     // If this method is called from within this method, infinite recursion can occur (3442218). Avoid this.
1582     if (m_inStopAllLoaders)
1583         return;
1584     
1585     // Calling stopLoading() on the provisional document loader can blow away
1586     // the frame from underneath.
1587     Ref<Frame> protect(m_frame);
1588
1589     m_inStopAllLoaders = true;
1590
1591     policyChecker().stopCheck();
1592
1593     // If no new load is in progress, we should clear the provisional item from history
1594     // before we call stopLoading.
1595     if (clearProvisionalItemPolicy == ShouldClearProvisionalItem)
1596         history().setProvisionalItem(nullptr);
1597
1598     for (RefPtr<Frame> child = m_frame.tree().firstChild(); child; child = child->tree().nextSibling())
1599         child->loader().stopAllLoaders(clearProvisionalItemPolicy);
1600     if (m_provisionalDocumentLoader)
1601         m_provisionalDocumentLoader->stopLoading();
1602     if (m_documentLoader)
1603         m_documentLoader->stopLoading();
1604
1605     setProvisionalDocumentLoader(nullptr);
1606
1607     m_checkTimer.stop();
1608
1609     m_inStopAllLoaders = false;    
1610 }
1611
1612 void FrameLoader::stopForUserCancel(bool deferCheckLoadComplete)
1613 {
1614     stopAllLoaders();
1615
1616 #if PLATFORM(IOS)
1617     // Lay out immediately when stopping to immediately clear the old page if we just committed this one
1618     // but haven't laid out/painted yet.
1619     // FIXME: Is this behavior specific to iOS? Or should we expose a setting to toggle this behavior?
1620     if (m_frame.view() && !m_frame.view()->didFirstLayout())
1621         m_frame.view()->layout();
1622 #endif
1623
1624     if (deferCheckLoadComplete)
1625         scheduleCheckLoadComplete();
1626     else if (m_frame.page())
1627         checkLoadComplete();
1628 }
1629
1630 DocumentLoader* FrameLoader::activeDocumentLoader() const
1631 {
1632     if (m_state == FrameStateProvisional)
1633         return m_provisionalDocumentLoader.get();
1634     return m_documentLoader.get();
1635 }
1636
1637 bool FrameLoader::isLoading() const
1638 {
1639     DocumentLoader* docLoader = activeDocumentLoader();
1640     if (!docLoader)
1641         return false;
1642     return docLoader->isLoading();
1643 }
1644
1645 bool FrameLoader::frameHasLoaded() const
1646 {
1647     return m_stateMachine.committedFirstRealDocumentLoad() || (m_provisionalDocumentLoader && !m_stateMachine.creatingInitialEmptyDocument()); 
1648 }
1649
1650 void FrameLoader::setDocumentLoader(DocumentLoader* loader)
1651 {
1652     if (!loader && !m_documentLoader)
1653         return;
1654     
1655     ASSERT(loader != m_documentLoader);
1656     ASSERT(!loader || loader->frameLoader() == this);
1657
1658     m_client.prepareForDataSourceReplacement();
1659     detachChildren();
1660
1661     // detachChildren() can trigger this frame's unload event, and therefore
1662     // script can run and do just about anything. For example, an unload event that calls
1663     // document.write("") on its parent frame can lead to a recursive detachChildren()
1664     // invocation for this frame. In that case, we can end up at this point with a
1665     // loader that hasn't been deleted but has been detached from its frame. Such a
1666     // DocumentLoader has been sufficiently detached that we'll end up in an inconsistent
1667     // state if we try to use it.
1668     if (loader && !loader->frame())
1669         return;
1670
1671     if (m_documentLoader)
1672         m_documentLoader->detachFromFrame();
1673
1674     m_documentLoader = loader;
1675 }
1676
1677 void FrameLoader::setPolicyDocumentLoader(DocumentLoader* loader)
1678 {
1679     if (m_policyDocumentLoader == loader)
1680         return;
1681
1682     if (loader)
1683         loader->attachToFrame(m_frame);
1684     if (m_policyDocumentLoader
1685             && m_policyDocumentLoader != m_provisionalDocumentLoader
1686             && m_policyDocumentLoader != m_documentLoader)
1687         m_policyDocumentLoader->detachFromFrame();
1688
1689     m_policyDocumentLoader = loader;
1690 }
1691
1692 void FrameLoader::setProvisionalDocumentLoader(DocumentLoader* loader)
1693 {
1694     ASSERT(!loader || !m_provisionalDocumentLoader);
1695     ASSERT(!loader || loader->frameLoader() == this);
1696
1697     if (m_provisionalDocumentLoader && m_provisionalDocumentLoader != m_documentLoader)
1698         m_provisionalDocumentLoader->detachFromFrame();
1699
1700     m_provisionalDocumentLoader = loader;
1701 }
1702
1703 void FrameLoader::setState(FrameState newState)
1704 {    
1705     m_state = newState;
1706     
1707     if (newState == FrameStateProvisional)
1708         provisionalLoadStarted();
1709     else if (newState == FrameStateComplete) {
1710         frameLoadCompleted();
1711         if (m_documentLoader)
1712             m_documentLoader->stopRecordingResponses();
1713     }
1714 }
1715
1716 void FrameLoader::clearProvisionalLoad()
1717 {
1718     setProvisionalDocumentLoader(nullptr);
1719     m_progressTracker->progressCompleted();
1720     setState(FrameStateComplete);
1721 }
1722
1723 void FrameLoader::commitProvisionalLoad()
1724 {
1725     RefPtr<DocumentLoader> pdl = m_provisionalDocumentLoader;
1726     Ref<Frame> protect(m_frame);
1727
1728     std::unique_ptr<CachedPage> cachedPage;
1729     if (m_loadingFromCachedPage && history().provisionalItem())
1730         cachedPage = PageCache::singleton().take(*history().provisionalItem(), m_frame.page());
1731
1732     LOG(PageCache, "WebCoreLoading %s: About to commit provisional load from previous URL '%s' to new URL '%s'", m_frame.tree().uniqueName().string().utf8().data(),
1733         m_frame.document() ? m_frame.document()->url().stringCenterEllipsizedToLength().utf8().data() : "",
1734         pdl ? pdl->url().stringCenterEllipsizedToLength().utf8().data() : "<no provisional DocumentLoader>");
1735
1736 #if PLATFORM(IOS)
1737     // In the case where we are not navigating to a cached page, and the system is under (speculative) memory pressure,
1738     // we can try to preemptively release some of the pages in the cache.
1739     // FIXME: Right now the capacity is 1 on iOS devices with 256 MB of RAM, so this will always blow away the whole
1740     // page cache. We could still preemptively prune the page cache while navigating to a cached page if capacity > 1.
1741     // See <rdar://problem/11779846> for more details.
1742     if (!cachedPage) {
1743         if (MemoryPressureHandler::singleton().isUnderMemoryPressure()) {
1744             LOG(MemoryPressure, "Pruning page cache because under memory pressure at: %s", __PRETTY_FUNCTION__);
1745             LOG(PageCache, "Pruning page cache to 0 due to memory pressure");
1746             // Don't cache any page if we are under memory pressure.
1747             PageCache::singleton().pruneToSizeNow(0, PruningReason::MemoryPressure);
1748         } else if (systemMemoryLevel() <= memoryLevelThresholdToPrunePageCache) {
1749             LOG(MemoryPressure, "Pruning page cache because system memory level is %d at: %s", systemMemoryLevel(), __PRETTY_FUNCTION__);
1750             auto& pageCache = PageCache::singleton();
1751             LOG(PageCache, "Pruning page cache to %d due to low memory (level %d less or equal to %d threshold)", pageCache.maxSize() / 2, systemMemoryLevel(), memoryLevelThresholdToPrunePageCache);
1752             pageCache.pruneToSizeNow(pageCache.maxSize() / 2, PruningReason::MemoryPressure);
1753         }
1754     }
1755 #endif
1756
1757     willTransitionToCommitted();
1758
1759     // Check to see if we need to cache the page we are navigating away from into the back/forward cache.
1760     // We are doing this here because we know for sure that a new page is about to be loaded.
1761     HistoryItem& item = *history().currentItem();
1762     if (!m_frame.tree().parent() && PageCache::singleton().canCache(m_frame.page()) && !item.isInPageCache())
1763         PageCache::singleton().add(item, *m_frame.page());
1764
1765     if (m_loadType != FrameLoadType::Replace)
1766         closeOldDataSources();
1767
1768     if (!cachedPage && !m_stateMachine.creatingInitialEmptyDocument())
1769         m_client.makeRepresentation(pdl.get());
1770
1771     transitionToCommitted(cachedPage.get());
1772
1773     if (pdl && m_documentLoader) {
1774         // Check if the destination page is allowed to access the previous page's timing information.
1775         Ref<SecurityOrigin> securityOrigin(SecurityOrigin::create(pdl->request().url()));
1776         m_documentLoader->timing().setHasSameOriginAsPreviousDocument(securityOrigin.get().canRequest(m_previousURL));
1777     }
1778
1779     // Call clientRedirectCancelledOrFinished() here so that the frame load delegate is notified that the redirect's
1780     // status has changed, if there was a redirect.  The frame load delegate may have saved some state about
1781     // the redirect in its -webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:.  Since we are
1782     // just about to commit a new page, there cannot possibly be a pending redirect at this point.
1783     if (m_sentRedirectNotification)
1784         clientRedirectCancelledOrFinished(false);
1785     
1786     if (cachedPage && cachedPage->document()) {
1787 #if PLATFORM(IOS)
1788         // FIXME: CachedPage::restore() would dispatch viewport change notification. However UIKit expects load
1789         // commit to happen before any changes to viewport arguments and dealing with this there is difficult.
1790         m_frame.page()->chrome().setDispatchViewportDataDidChangeSuppressed(true);
1791 #endif
1792         prepareForCachedPageRestore();
1793
1794         // FIXME: This API should be turned around so that we ground CachedPage into the Page.
1795         cachedPage->restore(*m_frame.page());
1796
1797         dispatchDidCommitLoad();
1798 #if PLATFORM(IOS)
1799         m_frame.page()->chrome().setDispatchViewportDataDidChangeSuppressed(false);
1800         m_frame.page()->chrome().dispatchViewportPropertiesDidChange(m_frame.page()->viewportArguments());
1801 #endif
1802         // If we have a title let the WebView know about it. 
1803         StringWithDirection title = m_documentLoader->title();
1804         if (!title.isNull())
1805             m_client.dispatchDidReceiveTitle(title);
1806
1807         checkCompleted();
1808     } else
1809         didOpenURL();
1810
1811     LOG(Loading, "WebCoreLoading %s: Finished committing provisional load to URL %s", m_frame.tree().uniqueName().string().utf8().data(),
1812         m_frame.document() ? m_frame.document()->url().stringCenterEllipsizedToLength().utf8().data() : "");
1813
1814     if (m_loadType == FrameLoadType::Standard && m_documentLoader->isClientRedirect())
1815         history().updateForClientRedirect();
1816
1817     if (m_loadingFromCachedPage) {
1818 #if PLATFORM(IOS)
1819         // Note, didReceiveDocType is expected to be called for cached pages. See <rdar://problem/5906758> for more details.
1820         if (m_frame.document()->doctype() && m_frame.page())
1821             m_frame.page()->chrome().didReceiveDocType(&m_frame);
1822 #endif
1823         m_frame.document()->resume();
1824
1825         // Force a layout to update view size and thereby update scrollbars.
1826 #if PLATFORM(IOS)
1827         if (!m_client.forceLayoutOnRestoreFromPageCache())
1828             m_frame.view()->forceLayout();
1829 #else
1830         m_frame.view()->forceLayout();
1831 #endif
1832
1833         for (auto& response : m_documentLoader->responses()) {
1834             // FIXME: If the WebKit client changes or cancels the request, this is not respected.
1835             ResourceError error;
1836             unsigned long identifier;
1837             ResourceRequest request(response.url());
1838             requestFromDelegate(request, identifier, error);
1839             // FIXME: If we get a resource with more than 2B bytes, this code won't do the right thing.
1840             // However, with today's computers and networking speeds, this won't happen in practice.
1841             // Could be an issue with a giant local file.
1842             notifier().sendRemainingDelegateMessages(m_documentLoader.get(), identifier, request, response, 0, static_cast<int>(response.expectedContentLength()), 0, error);
1843         }
1844
1845         // FIXME: Why only this frame and not parent frames?
1846         checkLoadCompleteForThisFrame();
1847     }
1848 }
1849
1850 void FrameLoader::transitionToCommitted(CachedPage* cachedPage)
1851 {
1852     ASSERT(m_client.hasWebView());
1853     ASSERT(m_state == FrameStateProvisional);
1854
1855     if (m_state != FrameStateProvisional)
1856         return;
1857
1858     if (FrameView* view = m_frame.view()) {
1859         if (ScrollAnimator* scrollAnimator = view->existingScrollAnimator())
1860             scrollAnimator->cancelAnimations();
1861     }
1862
1863     m_client.setCopiesOnScroll();
1864     history().updateForCommit();
1865
1866     // The call to closeURL() invokes the unload event handler, which can execute arbitrary
1867     // JavaScript. If the script initiates a new load, we need to abandon the current load,
1868     // or the two will stomp each other.
1869     DocumentLoader* pdl = m_provisionalDocumentLoader.get();
1870     if (m_documentLoader)
1871         closeURL();
1872     if (pdl != m_provisionalDocumentLoader)
1873         return;
1874
1875     // Nothing else can interupt this commit - set the Provisional->Committed transition in stone
1876     if (m_documentLoader)
1877         m_documentLoader->stopLoadingSubresources();
1878     if (m_documentLoader)
1879         m_documentLoader->stopLoadingPlugIns();
1880
1881     setDocumentLoader(m_provisionalDocumentLoader.get());
1882     setProvisionalDocumentLoader(nullptr);
1883
1884     if (pdl != m_documentLoader) {
1885         ASSERT(m_state == FrameStateComplete);
1886         return;
1887     }
1888
1889     setState(FrameStateCommittedPage);
1890
1891 #if ENABLE(TOUCH_EVENTS) && !PLATFORM(IOS)
1892     if (m_frame.isMainFrame())
1893         m_frame.page()->chrome().client().needTouchEvents(false);
1894 #endif
1895
1896     // Handle adding the URL to the back/forward list.
1897     DocumentLoader* dl = m_documentLoader.get();
1898
1899     switch (m_loadType) {
1900     case FrameLoadType::Forward:
1901     case FrameLoadType::Back:
1902     case FrameLoadType::IndexedBackForward:
1903         if (m_frame.page()) {
1904             // If the first load within a frame is a navigation within a back/forward list that was attached
1905             // without any of the items being loaded then we need to update the history in a similar manner as
1906             // for a standard load with the exception of updating the back/forward list (<rdar://problem/8091103>).
1907             if (!m_stateMachine.committedFirstRealDocumentLoad() && m_frame.isMainFrame())
1908                 history().updateForStandardLoad(HistoryController::UpdateAllExceptBackForwardList);
1909
1910             history().updateForBackForwardNavigation();
1911
1912             // For cached pages, CachedFrame::restore will take care of firing the popstate event with the history item's state object
1913             if (history().currentItem() && !cachedPage)
1914                 m_pendingStateObject = history().currentItem()->stateObject();
1915
1916             // Create a document view for this document, or used the cached view.
1917             if (cachedPage) {
1918                 DocumentLoader* cachedDocumentLoader = cachedPage->documentLoader();
1919                 ASSERT(cachedDocumentLoader);
1920                 cachedDocumentLoader->attachToFrame(m_frame);
1921                 m_client.transitionToCommittedFromCachedFrame(cachedPage->cachedMainFrame());
1922             } else
1923                 m_client.transitionToCommittedForNewPage();
1924         }
1925         break;
1926
1927     case FrameLoadType::Reload:
1928     case FrameLoadType::ReloadFromOrigin:
1929     case FrameLoadType::Same:
1930     case FrameLoadType::Replace:
1931         history().updateForReload();
1932         m_client.transitionToCommittedForNewPage();
1933         break;
1934
1935     case FrameLoadType::Standard:
1936         history().updateForStandardLoad();
1937         if (m_frame.view())
1938             m_frame.view()->setScrollbarsSuppressed(true);
1939         m_client.transitionToCommittedForNewPage();
1940         break;
1941
1942     case FrameLoadType::RedirectWithLockedBackForwardList:
1943         history().updateForRedirectWithLockedBackForwardList();
1944         m_client.transitionToCommittedForNewPage();
1945         break;
1946
1947     // FIXME Remove this check when dummy ds is removed (whatever "dummy ds" is).
1948     // An exception should be thrown if we're in the FrameLoadTypeUninitialized state.
1949     default:
1950         ASSERT_NOT_REACHED();
1951     }
1952
1953     m_documentLoader->writer().setMIMEType(dl->responseMIMEType());
1954
1955     // Tell the client we've committed this URL.
1956     ASSERT(m_frame.view());
1957
1958     if (m_stateMachine.creatingInitialEmptyDocument())
1959         return;
1960
1961     if (!m_stateMachine.committedFirstRealDocumentLoad())
1962         m_stateMachine.advanceTo(FrameLoaderStateMachine::DisplayingInitialEmptyDocumentPostCommit);
1963 }
1964
1965 void FrameLoader::clientRedirectCancelledOrFinished(bool cancelWithLoadInProgress)
1966 {
1967     // Note that -webView:didCancelClientRedirectForFrame: is called on the frame load delegate even if
1968     // the redirect succeeded.  We should either rename this API, or add a new method, like
1969     // -webView:didFinishClientRedirectForFrame:
1970     m_client.dispatchDidCancelClientRedirect();
1971
1972     if (!cancelWithLoadInProgress)
1973         m_quickRedirectComing = false;
1974
1975     m_sentRedirectNotification = false;
1976 }
1977
1978 void FrameLoader::clientRedirected(const URL& url, double seconds, double fireDate, LockBackForwardList lockBackForwardList)
1979 {
1980     m_client.dispatchWillPerformClientRedirect(url, seconds, fireDate);
1981     
1982     // Remember that we sent a redirect notification to the frame load delegate so that when we commit
1983     // the next provisional load, we can send a corresponding -webView:didCancelClientRedirectForFrame:
1984     m_sentRedirectNotification = true;
1985     
1986     // If a "quick" redirect comes in, we set a special mode so we treat the next
1987     // load as part of the original navigation. If we don't have a document loader, we have
1988     // no "original" load on which to base a redirect, so we treat the redirect as a normal load.
1989     // Loads triggered by JavaScript form submissions never count as quick redirects.
1990     m_quickRedirectComing = (lockBackForwardList == LockBackForwardList::Yes || history().currentItemShouldBeReplaced()) && m_documentLoader && !m_isExecutingJavaScriptFormAction;
1991 }
1992
1993 bool FrameLoader::shouldReload(const URL& currentURL, const URL& destinationURL)
1994 {
1995     // This function implements the rule: "Don't reload if navigating by fragment within
1996     // the same URL, but do reload if going to a new URL or to the same URL with no
1997     // fragment identifier at all."
1998     if (!destinationURL.hasFragmentIdentifier())
1999         return true;
2000     return !equalIgnoringFragmentIdentifier(currentURL, destinationURL);
2001 }
2002
2003 void FrameLoader::closeOldDataSources()
2004 {
2005     // FIXME: Is it important for this traversal to be postorder instead of preorder?
2006     // If so, add helpers for postorder traversal, and use them. If not, then lets not
2007     // use a recursive algorithm here.
2008     for (Frame* child = m_frame.tree().firstChild(); child; child = child->tree().nextSibling())
2009         child->loader().closeOldDataSources();
2010     
2011     if (m_documentLoader)
2012         m_client.dispatchWillClose();
2013
2014     m_client.setMainFrameDocumentReady(false); // stop giving out the actual DOMDocument to observers
2015 }
2016
2017 void FrameLoader::prepareForCachedPageRestore()
2018 {
2019     ASSERT(!m_frame.tree().parent());
2020     ASSERT(m_frame.page());
2021     ASSERT(m_frame.isMainFrame());
2022
2023     m_frame.navigationScheduler().cancel();
2024
2025     // We still have to close the previous part page.
2026     closeURL();
2027     
2028     // Delete old status bar messages (if it _was_ activated on last URL).
2029     if (m_frame.script().canExecuteScripts(NotAboutToExecuteScript)) {
2030         DOMWindow* window = m_frame.document()->domWindow();
2031         window->setStatus(String());
2032         window->setDefaultStatus(String());
2033     }
2034 }
2035
2036 void FrameLoader::open(CachedFrameBase& cachedFrame)
2037 {
2038     m_isComplete = false;
2039     
2040     // Don't re-emit the load event.
2041     m_didCallImplicitClose = true;
2042
2043     URL url = cachedFrame.url();
2044
2045     // FIXME: I suspect this block of code doesn't do anything.
2046     if (url.protocolIsInHTTPFamily() && !url.host().isEmpty() && url.path().isEmpty())
2047         url.setPath("/");
2048
2049     started();
2050     Document* document = cachedFrame.document();
2051     ASSERT(document);
2052     ASSERT(document->domWindow());
2053
2054     clear(document, true, true, cachedFrame.isMainFrame());
2055
2056     document->setInPageCache(false);
2057
2058     m_needsClear = true;
2059     m_isComplete = false;
2060     m_didCallImplicitClose = false;
2061     m_outgoingReferrer = url.string();
2062
2063     FrameView* view = cachedFrame.view();
2064     
2065     // When navigating to a CachedFrame its FrameView should never be null.  If it is we'll crash in creative ways downstream.
2066     ASSERT(view);
2067     view->setWasScrolledByUser(false);
2068
2069     Optional<IntRect> previousViewFrameRect = m_frame.view() ?  m_frame.view()->frameRect() : Optional<IntRect>(Nullopt);
2070     m_frame.setView(view);
2071
2072     // Use the previous ScrollView's frame rect.
2073     if (previousViewFrameRect)
2074         view->setFrameRect(previousViewFrameRect.value());
2075     
2076     m_frame.setDocument(document);
2077     document->domWindow()->resumeFromPageCache();
2078
2079     updateFirstPartyForCookies();
2080
2081     cachedFrame.restore();
2082 }
2083
2084 bool FrameLoader::isHostedByObjectElement() const
2085 {
2086     HTMLFrameOwnerElement* owner = m_frame.ownerElement();
2087     return owner && owner->hasTagName(objectTag);
2088 }
2089
2090 bool FrameLoader::isReplacing() const
2091 {
2092     return m_loadType == FrameLoadType::Replace;
2093 }
2094
2095 void FrameLoader::setReplacing()
2096 {
2097     m_loadType = FrameLoadType::Replace;
2098 }
2099
2100 bool FrameLoader::subframeIsLoading() const
2101 {
2102     // It's most likely that the last added frame is the last to load so we walk backwards.
2103     for (Frame* child = m_frame.tree().lastChild(); child; child = child->tree().previousSibling()) {
2104         FrameLoader& childLoader = child->loader();
2105         DocumentLoader* documentLoader = childLoader.documentLoader();
2106         if (documentLoader && documentLoader->isLoadingInAPISense())
2107             return true;
2108         documentLoader = childLoader.provisionalDocumentLoader();
2109         if (documentLoader && documentLoader->isLoadingInAPISense())
2110             return true;
2111         documentLoader = childLoader.policyDocumentLoader();
2112         if (documentLoader)
2113             return true;
2114     }
2115     return false;
2116 }
2117
2118 void FrameLoader::willChangeTitle(DocumentLoader* loader)
2119 {
2120     m_client.willChangeTitle(loader);
2121 }
2122
2123 FrameLoadType FrameLoader::loadType() const
2124 {
2125     return m_loadType;
2126 }
2127     
2128 CachePolicy FrameLoader::subresourceCachePolicy() const
2129 {
2130     if (m_isComplete)
2131         return CachePolicyVerify;
2132
2133     if (m_loadType == FrameLoadType::ReloadFromOrigin)
2134         return CachePolicyReload;
2135
2136     if (Frame* parentFrame = m_frame.tree().parent()) {
2137         CachePolicy parentCachePolicy = parentFrame->loader().subresourceCachePolicy();
2138         if (parentCachePolicy != CachePolicyVerify)
2139             return parentCachePolicy;
2140     }
2141     
2142     switch (m_loadType) {
2143     case FrameLoadType::Reload:
2144         return CachePolicyRevalidate;
2145     case FrameLoadType::Back:
2146     case FrameLoadType::Forward:
2147     case FrameLoadType::IndexedBackForward:
2148         return CachePolicyHistoryBuffer;
2149     case FrameLoadType::ReloadFromOrigin:
2150         ASSERT_NOT_REACHED(); // Already handled above.
2151         return CachePolicyReload;
2152     case FrameLoadType::RedirectWithLockedBackForwardList:
2153     case FrameLoadType::Replace:
2154     case FrameLoadType::Same:
2155     case FrameLoadType::Standard:
2156         return CachePolicyVerify;
2157     }
2158
2159     RELEASE_ASSERT_NOT_REACHED();
2160     return CachePolicyVerify;
2161 }
2162
2163 void FrameLoader::checkLoadCompleteForThisFrame()
2164 {
2165     ASSERT(m_client.hasWebView());
2166
2167     switch (m_state) {
2168         case FrameStateProvisional: {
2169             if (!m_provisionalLoadErrorBeingHandledURL.isEmpty())
2170                 return;
2171
2172             RefPtr<DocumentLoader> pdl = m_provisionalDocumentLoader;
2173             if (!pdl)
2174                 return;
2175                 
2176             // If we've received any errors we may be stuck in the provisional state and actually complete.
2177             const ResourceError& error = pdl->mainDocumentError();
2178             if (error.isNull())
2179                 return;
2180
2181             // Check all children first.
2182             RefPtr<HistoryItem> item;
2183             if (Page* page = m_frame.page())
2184                 if (isBackForwardLoadType(loadType()))
2185                     // Reset the back forward list to the last committed history item at the top level.
2186                     item = page->mainFrame().loader().history().currentItem();
2187                 
2188             // Only reset if we aren't already going to a new provisional item.
2189             bool shouldReset = !history().provisionalItem();
2190             if (!pdl->isLoadingInAPISense() || pdl->isStopping()) {
2191                 m_provisionalLoadErrorBeingHandledURL = m_provisionalDocumentLoader->url();
2192                 m_client.dispatchDidFailProvisionalLoad(error);
2193                 m_provisionalLoadErrorBeingHandledURL = { };
2194
2195                 ASSERT(!pdl->isLoading());
2196
2197                 // If we're in the middle of loading multipart data, we need to restore the document loader.
2198                 if (isReplacing() && !m_documentLoader.get())
2199                     setDocumentLoader(m_provisionalDocumentLoader.get());
2200
2201                 // Finish resetting the load state, but only if another load hasn't been started by the
2202                 // delegate callback.
2203                 if (pdl == m_provisionalDocumentLoader)
2204                     clearProvisionalLoad();
2205                 else if (activeDocumentLoader()) {
2206                     URL unreachableURL = activeDocumentLoader()->unreachableURL();
2207                     if (!unreachableURL.isEmpty() && unreachableURL == pdl->request().url())
2208                         shouldReset = false;
2209                 }
2210             }
2211             if (shouldReset && item)
2212                 if (Page* page = m_frame.page()) {
2213                     page->backForward().setCurrentItem(item.get());
2214                     m_frame.loader().client().updateGlobalHistoryItemForPage();
2215                 }
2216             return;
2217         }
2218         
2219         case FrameStateCommittedPage: {
2220             DocumentLoader* dl = m_documentLoader.get();            
2221             if (!dl || (dl->isLoadingInAPISense() && !dl->isStopping()))
2222                 return;
2223
2224             setState(FrameStateComplete);
2225
2226             // FIXME: Is this subsequent work important if we already navigated away?
2227             // Maybe there are bugs because of that, or extra work we can skip because
2228             // the new page is ready.
2229
2230             m_client.forceLayoutForNonHTML();
2231              
2232             // If the user had a scroll point, scroll to it, overriding the anchor point if any.
2233             if (m_frame.page()) {
2234                 if (isBackForwardLoadType(m_loadType) || m_loadType == FrameLoadType::Reload || m_loadType == FrameLoadType::ReloadFromOrigin)
2235                     history().restoreScrollPositionAndViewState();
2236             }
2237
2238             if (m_stateMachine.creatingInitialEmptyDocument() || !m_stateMachine.committedFirstRealDocumentLoad())
2239                 return;
2240
2241             m_progressTracker->progressCompleted();
2242             Page* page = m_frame.page();
2243             if (page) {
2244                 if (m_frame.isMainFrame())
2245                     page->resetRelevantPaintedObjectCounter();
2246             }
2247
2248             const ResourceError& error = dl->mainDocumentError();
2249
2250             AXObjectCache::AXLoadingEvent loadingEvent;
2251             if (!error.isNull()) {
2252                 m_client.dispatchDidFailLoad(error);
2253                 loadingEvent = AXObjectCache::AXLoadingFailed;
2254             } else {
2255                 m_client.dispatchDidFinishLoad();
2256                 loadingEvent = AXObjectCache::AXLoadingFinished;
2257             }
2258
2259             // Notify accessibility.
2260             if (AXObjectCache* cache = m_frame.document()->existingAXObjectCache())
2261                 cache->frameLoadingEventNotification(&m_frame, loadingEvent);
2262
2263             // The above calls to dispatchDidFinishLoad() might have detached the Frame
2264             // from its Page and also might have caused Page to be deleted.
2265             // Don't assume 'page' is still available to use.
2266             if (m_frame.isMainFrame() && m_frame.page()) {
2267                 ASSERT(&m_frame.page()->mainFrame() == &m_frame);
2268                 m_frame.page()->mainFrame().diagnosticLoggingClient().logDiagnosticMessageWithResult(DiagnosticLoggingKeys::pageLoadedKey(), emptyString(), error.isNull() ? DiagnosticLoggingResultPass : DiagnosticLoggingResultFail, ShouldSample::Yes);
2269             }
2270
2271             return;
2272         }
2273         
2274         case FrameStateComplete:
2275             m_loadType = FrameLoadType::Standard;
2276             frameLoadCompleted();
2277             return;
2278     }
2279
2280     ASSERT_NOT_REACHED();
2281 }
2282
2283 void FrameLoader::continueLoadAfterWillSubmitForm()
2284 {
2285     if (!m_provisionalDocumentLoader)
2286         return;
2287
2288     prepareForLoadStart();
2289     
2290     // The load might be cancelled inside of prepareForLoadStart(), nulling out the m_provisionalDocumentLoader, 
2291     // so we need to null check it again.
2292     if (!m_provisionalDocumentLoader)
2293         return;
2294
2295     DocumentLoader* activeDocLoader = activeDocumentLoader();
2296     if (activeDocLoader && activeDocLoader->isLoadingMainResource())
2297         return;
2298
2299     m_loadingFromCachedPage = false;
2300     m_provisionalDocumentLoader->startLoadingMainResource();
2301 }
2302
2303 static URL originatingURLFromBackForwardList(Page* page)
2304 {
2305     // FIXME: Can this logic be replaced with m_frame.document()->firstPartyForCookies()?
2306     // It has the same meaning of "page a user thinks is the current one".
2307
2308     URL originalURL;
2309     int backCount = page->backForward().backCount();
2310     for (int backIndex = 0; backIndex <= backCount; backIndex++) {
2311         // FIXME: At one point we had code here to check a "was user gesture" flag.
2312         // Do we need to restore that logic?
2313         HistoryItem* historyItem = page->backForward().itemAtIndex(-backIndex);
2314         if (!historyItem)
2315             continue;
2316
2317         originalURL = historyItem->originalURL(); 
2318         if (!originalURL.isNull()) 
2319             return originalURL;
2320     }
2321
2322     return URL();
2323 }
2324
2325 void FrameLoader::setOriginalURLForDownloadRequest(ResourceRequest& request)
2326 {
2327     URL originalURL;
2328     
2329     // If there is no referrer, assume that the download was initiated directly, so current document is
2330     // completely unrelated to it. See <rdar://problem/5294691>.
2331     // FIXME: Referrer is not sent in many other cases, so we will often miss this important information.
2332     // Find a better way to decide whether the download was unrelated to current document.
2333     if (!request.httpReferrer().isNull()) {
2334         // find the first item in the history that was originated by the user
2335         originalURL = originatingURLFromBackForwardList(m_frame.page());
2336     }
2337
2338     if (originalURL.isNull())
2339         originalURL = request.url();
2340
2341     if (!originalURL.protocol().isEmpty() && !originalURL.host().isEmpty()) {
2342         unsigned port = originalURL.port();
2343
2344         // 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.
2345         // 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.
2346         String hostOnlyURLString;
2347         if (port)
2348             hostOnlyURLString = makeString(originalURL.protocol(), "://", originalURL.host(), ':', String::number(port));
2349         else
2350             hostOnlyURLString = makeString(originalURL.protocol(), "://", originalURL.host());
2351
2352         // FIXME: Rename firstPartyForCookies back to mainDocumentURL. It was a mistake to think that it was only used for cookies.
2353         request.setFirstPartyForCookies(URL(URL(), hostOnlyURLString));
2354     }
2355 }
2356
2357 void FrameLoader::didLayout(LayoutMilestones milestones)
2358 {
2359     ASSERT(m_frame.isMainFrame());
2360
2361     m_client.dispatchDidLayout(milestones);
2362 }
2363
2364 void FrameLoader::didFirstLayout()
2365 {
2366 #if PLATFORM(IOS)
2367     // Only send layout-related delegate callbacks synchronously for the main frame to
2368     // avoid reentering layout for the main frame while delivering a layout-related delegate
2369     // callback for a subframe.
2370     if (&m_frame != &m_frame.page()->mainFrame())
2371         return;
2372 #endif
2373     if (m_frame.page() && isBackForwardLoadType(m_loadType))
2374         history().restoreScrollPositionAndViewState();
2375
2376     if (m_stateMachine.committedFirstRealDocumentLoad() && !m_stateMachine.isDisplayingInitialEmptyDocument() && !m_stateMachine.firstLayoutDone())
2377         m_stateMachine.advanceTo(FrameLoaderStateMachine::FirstLayoutDone);
2378 }
2379
2380 void FrameLoader::frameLoadCompleted()
2381 {
2382     // Note: Can be called multiple times.
2383
2384     m_client.frameLoadCompleted();
2385
2386     history().updateForFrameLoadCompleted();
2387
2388     // After a canceled provisional load, firstLayoutDone is false.
2389     // Reset it to true if we're displaying a page.
2390     if (m_documentLoader && m_stateMachine.committedFirstRealDocumentLoad() && !m_stateMachine.isDisplayingInitialEmptyDocument() && !m_stateMachine.firstLayoutDone())
2391         m_stateMachine.advanceTo(FrameLoaderStateMachine::FirstLayoutDone);
2392 }
2393
2394 void FrameLoader::detachChildren()
2395 {
2396     Vector<Ref<Frame>, 16> childrenToDetach;
2397     childrenToDetach.reserveInitialCapacity(m_frame.tree().childCount());
2398     for (Frame* child = m_frame.tree().lastChild(); child; child = child->tree().previousSibling())
2399         childrenToDetach.uncheckedAppend(*child);
2400     for (auto& child : childrenToDetach)
2401         child->loader().detachFromParent();
2402 }
2403
2404 void FrameLoader::closeAndRemoveChild(Frame* child)
2405 {
2406     child->tree().detachFromParent();
2407
2408     child->setView(nullptr);
2409     if (child->ownerElement() && child->page())
2410         child->page()->decrementSubframeCount();
2411     child->willDetachPage();
2412     child->detachFromPage();
2413
2414     m_frame.tree().removeChild(child);
2415 }
2416
2417 // Called every time a resource is completely loaded or an error is received.
2418 void FrameLoader::checkLoadComplete()
2419 {
2420     ASSERT(m_client.hasWebView());
2421     
2422     m_shouldCallCheckLoadComplete = false;
2423
2424     if (!m_frame.page())
2425         return;
2426
2427     // FIXME: Always traversing the entire frame tree is a bit inefficient, but 
2428     // is currently needed in order to null out the previous history item for all frames.
2429     Vector<Ref<Frame>, 16> frames;
2430     for (Frame* frame = &m_frame.mainFrame(); frame; frame = frame->tree().traverseNext())
2431         frames.append(*frame);
2432
2433     // To process children before their parents, iterate the vector backwards.
2434     for (auto frame = frames.rbegin(); frame != frames.rend(); ++frame) {
2435         if ((*frame)->page())
2436             (*frame)->loader().checkLoadCompleteForThisFrame();
2437     }
2438 }
2439
2440 int FrameLoader::numPendingOrLoadingRequests(bool recurse) const
2441 {
2442     if (!recurse)
2443         return m_frame.document()->cachedResourceLoader().requestCount();
2444
2445     int count = 0;
2446     for (Frame* frame = &m_frame; frame; frame = frame->tree().traverseNext(&m_frame))
2447         count += frame->document()->cachedResourceLoader().requestCount();
2448     return count;
2449 }
2450
2451 String FrameLoader::userAgent(const URL& url) const
2452 {
2453     return m_client.userAgent(url);
2454 }
2455
2456 void FrameLoader::dispatchOnloadEvents()
2457 {
2458     m_client.dispatchDidDispatchOnloadEvents();
2459
2460     if (documentLoader())
2461         documentLoader()->dispatchOnloadEvents();
2462 }
2463
2464 void FrameLoader::frameDetached()
2465 {
2466     stopAllLoaders();
2467     m_frame.document()->stopActiveDOMObjects();
2468     detachFromParent();
2469 }
2470
2471 void FrameLoader::detachFromParent()
2472 {
2473     Ref<Frame> protect(m_frame);
2474
2475     closeURL();
2476     history().saveScrollPositionAndViewStateToItem(history().currentItem());
2477     detachChildren();
2478     // stopAllLoaders() needs to be called after detachChildren(), because detachedChildren()
2479     // will trigger the unload event handlers of any child frames, and those event
2480     // handlers might start a new subresource load in this frame.
2481     stopAllLoaders();
2482
2483     InspectorInstrumentation::frameDetachedFromParent(m_frame);
2484
2485     detachViewsAndDocumentLoader();
2486
2487     m_progressTracker = nullptr;
2488
2489     if (Frame* parent = m_frame.tree().parent()) {
2490         parent->loader().closeAndRemoveChild(&m_frame);
2491         parent->loader().scheduleCheckCompleted();
2492     } else {
2493         m_frame.setView(nullptr);
2494         m_frame.willDetachPage();
2495         m_frame.detachFromPage();
2496     }
2497 }
2498
2499 void FrameLoader::detachViewsAndDocumentLoader()
2500 {
2501     m_client.detachedFromParent2();
2502     setDocumentLoader(nullptr);
2503     m_client.detachedFromParent3();
2504 }
2505     
2506 void FrameLoader::addExtraFieldsToSubresourceRequest(ResourceRequest& request)
2507 {
2508     addExtraFieldsToRequest(request, m_loadType, false);
2509 }
2510
2511 void FrameLoader::addExtraFieldsToMainResourceRequest(ResourceRequest& request)
2512 {
2513     // FIXME: Using m_loadType seems wrong for some callers.
2514     // If we are only preparing to load the main resource, that is previous load's load type!
2515     addExtraFieldsToRequest(request, m_loadType, true);
2516 }
2517
2518 void FrameLoader::addExtraFieldsToRequest(ResourceRequest& request, FrameLoadType loadType, bool mainResource)
2519 {
2520     // Don't set the cookie policy URL if it's already been set.
2521     // But make sure to set it on all requests regardless of protocol, as it has significance beyond the cookie policy (<rdar://problem/6616664>).
2522     if (request.firstPartyForCookies().isEmpty()) {
2523         if (mainResource && m_frame.isMainFrame())
2524             request.setFirstPartyForCookies(request.url());
2525         else if (Document* document = m_frame.document())
2526             request.setFirstPartyForCookies(document->firstPartyForCookies());
2527     }
2528
2529     // The remaining modifications are only necessary for HTTP and HTTPS.
2530     if (!request.url().isEmpty() && !request.url().protocolIsInHTTPFamily())
2531         return;
2532
2533     applyUserAgent(request);
2534
2535     if (!mainResource) {
2536         if (request.isConditional())
2537             request.setCachePolicy(ReloadIgnoringCacheData);
2538         else if (documentLoader()->isLoadingInAPISense()) {
2539             // If we inherit cache policy from a main resource, we use the DocumentLoader's
2540             // original request cache policy for two reasons:
2541             // 1. For POST requests, we mutate the cache policy for the main resource,
2542             //    but we do not want this to apply to subresources
2543             // 2. Delegates that modify the cache policy using willSendRequest: should
2544             //    not affect any other resources. Such changes need to be done
2545             //    per request.
2546             ResourceRequestCachePolicy mainDocumentOriginalCachePolicy = documentLoader()->originalRequest().cachePolicy();
2547             // 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.
2548             // This policy is set on initial request too, but should not be inherited.
2549             ResourceRequestCachePolicy subresourceCachePolicy = (mainDocumentOriginalCachePolicy == ReturnCacheDataDontLoad) ? ReturnCacheDataElseLoad : mainDocumentOriginalCachePolicy;
2550             request.setCachePolicy(subresourceCachePolicy);
2551         } else
2552             request.setCachePolicy(UseProtocolCachePolicy);
2553
2554     // FIXME: Other FrameLoader functions have duplicated code for setting cache policy of main request when reloading.
2555     // It seems better to manage it explicitly than to hide the logic inside addExtraFieldsToRequest().
2556     } else if (loadType == FrameLoadType::Reload || loadType == FrameLoadType::ReloadFromOrigin || request.isConditional())
2557         request.setCachePolicy(ReloadIgnoringCacheData);
2558
2559     if (m_overrideCachePolicyForTesting)
2560         request.setCachePolicy(m_overrideCachePolicyForTesting.value());
2561     if (m_overrideResourceLoadPriorityForTesting)
2562         request.setPriority(m_overrideResourceLoadPriorityForTesting.value());
2563
2564     if (request.cachePolicy() == ReloadIgnoringCacheData) {
2565         if (loadType == FrameLoadType::Reload)
2566             request.setHTTPHeaderField(HTTPHeaderName::CacheControl, "max-age=0");
2567         else if (loadType == FrameLoadType::ReloadFromOrigin) {
2568             request.setHTTPHeaderField(HTTPHeaderName::CacheControl, "no-cache");
2569             request.setHTTPHeaderField(HTTPHeaderName::Pragma, "no-cache");
2570         }
2571     }
2572     
2573     if (mainResource)
2574         request.setHTTPAccept(defaultAcceptHeader);
2575
2576     // Make sure we send the Origin header.
2577     addHTTPOriginIfNeeded(request, String());
2578
2579     // Only set fallback array if it's still empty (later attempts may be incorrect, see bug 117818).
2580     if (request.responseContentDispositionEncodingFallbackArray().isEmpty()) {
2581         // Always try UTF-8. If that fails, try frame encoding (if any) and then the default.
2582         request.setResponseContentDispositionEncodingFallbackArray("UTF-8", m_frame.document()->encoding(), m_frame.settings().defaultTextEncodingName());
2583     }
2584 }
2585
2586 void FrameLoader::addHTTPOriginIfNeeded(ResourceRequest& request, const String& origin)
2587 {
2588     if (!request.httpOrigin().isEmpty())
2589         return;  // Request already has an Origin header.
2590
2591     // Don't send an Origin header for GET or HEAD to avoid privacy issues.
2592     // For example, if an intranet page has a hyperlink to an external web
2593     // site, we don't want to include the Origin of the request because it
2594     // will leak the internal host name. Similar privacy concerns have lead
2595     // to the widespread suppression of the Referer header at the network
2596     // layer.
2597     if (request.httpMethod() == "GET" || request.httpMethod() == "HEAD")
2598         return;
2599
2600     // For non-GET and non-HEAD methods, always send an Origin header so the
2601     // server knows we support this feature.
2602
2603     if (origin.isEmpty()) {
2604         // If we don't know what origin header to attach, we attach the value
2605         // for an empty origin.
2606         request.setHTTPOrigin(SecurityOrigin::createUnique()->toString());
2607         return;
2608     }
2609
2610     request.setHTTPOrigin(origin);
2611 }
2612
2613 void FrameLoader::loadPostRequest(const FrameLoadRequest& request, const String& referrer, FrameLoadType loadType, Event* event, PassRefPtr<FormState> prpFormState)
2614 {
2615     RefPtr<FormState> formState = prpFormState;
2616
2617     String frameName = request.frameName();
2618     LockHistory lockHistory = request.lockHistory();
2619     AllowNavigationToInvalidURL allowNavigationToInvalidURL = request.allowNavigationToInvalidURL();
2620     NewFrameOpenerPolicy openerPolicy = request.newFrameOpenerPolicy();
2621
2622     const ResourceRequest& inRequest = request.resourceRequest();
2623     const URL& url = inRequest.url();
2624     RefPtr<FormData> formData = inRequest.httpBody();
2625     const String& contentType = inRequest.httpContentType();
2626     String origin = inRequest.httpOrigin();
2627
2628     ResourceRequest workingResourceRequest(url);    
2629
2630     if (!referrer.isEmpty())
2631         workingResourceRequest.setHTTPReferrer(referrer);
2632     workingResourceRequest.setHTTPOrigin(origin);
2633     workingResourceRequest.setHTTPMethod("POST");
2634     workingResourceRequest.setHTTPBody(formData);
2635     workingResourceRequest.setHTTPContentType(contentType);
2636     addExtraFieldsToRequest(workingResourceRequest, loadType, true);
2637
2638     NavigationAction action(workingResourceRequest, loadType, true, event, request.shouldOpenExternalURLsPolicy());
2639
2640     if (!frameName.isEmpty()) {
2641         // The search for a target frame is done earlier in the case of form submission.
2642         if (Frame* targetFrame = formState ? 0 : findFrameForNavigation(frameName)) {
2643             targetFrame->loader().loadWithNavigationAction(workingResourceRequest, action, lockHistory, loadType, formState.release(), allowNavigationToInvalidURL);
2644             return;
2645         }
2646
2647         policyChecker().checkNewWindowPolicy(action, workingResourceRequest, formState.release(), frameName, [this, allowNavigationToInvalidURL, openerPolicy](const ResourceRequest& request, PassRefPtr<FormState> formState, const String& frameName, const NavigationAction& action, bool shouldContinue) {
2648             continueLoadAfterNewWindowPolicy(request, formState, frameName, action, shouldContinue, allowNavigationToInvalidURL, openerPolicy);
2649         });
2650         return;
2651     }
2652
2653     // must grab this now, since this load may stop the previous load and clear this flag
2654     bool isRedirect = m_quickRedirectComing;
2655     loadWithNavigationAction(workingResourceRequest, action, lockHistory, loadType, formState.release(), allowNavigationToInvalidURL);
2656     if (isRedirect) {
2657         m_quickRedirectComing = false;
2658         if (m_provisionalDocumentLoader)
2659             m_provisionalDocumentLoader->setIsClientRedirect(true);
2660     }
2661 }
2662
2663 unsigned long FrameLoader::loadResourceSynchronously(const ResourceRequest& request, StoredCredentials storedCredentials, ClientCredentialPolicy clientCredentialPolicy, ResourceError& error, ResourceResponse& response, RefPtr<SharedBuffer>& data)
2664 {
2665     ASSERT(m_frame.document());
2666     String referrer = SecurityPolicy::generateReferrerHeader(m_frame.document()->referrerPolicy(), request.url(), outgoingReferrer());
2667     
2668     ResourceRequest initialRequest = request;
2669     initialRequest.setTimeoutInterval(10);
2670     
2671     if (!referrer.isEmpty())
2672         initialRequest.setHTTPReferrer(referrer);
2673     addHTTPOriginIfNeeded(initialRequest, outgoingOrigin());
2674
2675     initialRequest.setFirstPartyForCookies(m_frame.mainFrame().loader().documentLoader()->request().url());
2676     
2677     addExtraFieldsToSubresourceRequest(initialRequest);
2678
2679     unsigned long identifier = 0;    
2680     ResourceRequest newRequest(initialRequest);
2681     requestFromDelegate(newRequest, identifier, error);
2682
2683 #if ENABLE(CONTENT_EXTENSIONS)
2684     if (error.isNull()) {
2685         if (auto* page = m_frame.page()) {
2686             if (auto* controller = page->userContentController()) {
2687                 if (m_documentLoader && controller->processContentExtensionRulesForLoad(newRequest, ResourceType::Raw, *m_documentLoader) == ContentExtensions::BlockedStatus::Blocked) {
2688                     newRequest = { };
2689                     error = ResourceError(errorDomainWebKitInternal, 0, initialRequest.url().string(), emptyString());
2690                     response = { };
2691                     data = nullptr;
2692                 }
2693             }
2694         }
2695     }
2696 #endif
2697
2698     if (error.isNull()) {
2699         ASSERT(!newRequest.isNull());
2700
2701         if (!documentLoader()->applicationCacheHost()->maybeLoadSynchronously(newRequest, error, response, data)) {
2702             Vector<char> buffer;
2703             platformStrategies()->loaderStrategy()->loadResourceSynchronously(networkingContext(), identifier, newRequest, storedCredentials, clientCredentialPolicy, error, response, buffer);
2704             data = SharedBuffer::adoptVector(buffer);
2705             documentLoader()->applicationCacheHost()->maybeLoadFallbackSynchronously(newRequest, error, response, data);
2706         }
2707     }
2708     notifier().sendRemainingDelegateMessages(m_documentLoader.get(), identifier, request, response, data ? data->data() : nullptr, data ? data->size() : 0, -1, error);
2709     return identifier;
2710 }
2711
2712 const ResourceRequest& FrameLoader::originalRequest() const
2713 {
2714     return activeDocumentLoader()->originalRequestCopy();
2715 }
2716
2717 void FrameLoader::receivedMainResourceError(const ResourceError& error)
2718 {
2719     // Retain because the stop may release the last reference to it.
2720     Ref<Frame> protect(m_frame);
2721
2722     RefPtr<DocumentLoader> loader = activeDocumentLoader();
2723     // FIXME: Don't want to do this if an entirely new load is going, so should check
2724     // that both data sources on the frame are either this or nil.
2725     stop();
2726     if (m_client.shouldFallBack(error))
2727         handleFallbackContent();
2728
2729     if (m_state == FrameStateProvisional && m_provisionalDocumentLoader) {
2730         if (m_submittedFormURL == m_provisionalDocumentLoader->originalRequestCopy().url())
2731             m_submittedFormURL = URL();
2732             
2733         // We might have made a page cache item, but now we're bailing out due to an error before we ever
2734         // transitioned to the new page (before WebFrameState == commit).  The goal here is to restore any state
2735         // so that the existing view (that wenever got far enough to replace) can continue being used.
2736         history().invalidateCurrentItemCachedPage();
2737         
2738         // Call clientRedirectCancelledOrFinished here so that the frame load delegate is notified that the redirect's
2739         // status has changed, if there was a redirect. The frame load delegate may have saved some state about
2740         // the redirect in its -webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:. Since we are definitely
2741         // not going to use this provisional resource, as it was cancelled, notify the frame load delegate that the redirect
2742         // has ended.
2743         if (m_sentRedirectNotification)
2744             clientRedirectCancelledOrFinished(false);
2745     }
2746
2747     checkCompleted();
2748     if (m_frame.page())
2749         checkLoadComplete();
2750 }
2751
2752 void FrameLoader::continueFragmentScrollAfterNavigationPolicy(const ResourceRequest& request, bool shouldContinue)
2753 {
2754     m_quickRedirectComing = false;
2755
2756     if (!shouldContinue)
2757         return;
2758
2759     // If we have a provisional request for a different document, a fragment scroll should cancel it.
2760     if (m_provisionalDocumentLoader && !equalIgnoringFragmentIdentifier(m_provisionalDocumentLoader->request().url(), request.url())) {
2761         m_provisionalDocumentLoader->stopLoading();
2762         setProvisionalDocumentLoader(nullptr);
2763     }
2764
2765     bool isRedirect = m_quickRedirectComing || policyChecker().loadType() == FrameLoadType::RedirectWithLockedBackForwardList;
2766     loadInSameDocument(request.url(), 0, !isRedirect);
2767 }
2768
2769 bool FrameLoader::shouldPerformFragmentNavigation(bool isFormSubmission, const String& httpMethod, FrameLoadType loadType, const URL& url)
2770 {
2771     // We don't do this if we are submitting a form with method other than "GET", explicitly reloading,
2772     // currently displaying a frameset, or if the URL does not have a fragment.
2773     // These rules were originally based on what KHTML was doing in KHTMLPart::openURL.
2774
2775     // FIXME: What about load types other than Standard and Reload?
2776
2777     return (!isFormSubmission || equalIgnoringCase(httpMethod, "GET"))
2778         && loadType != FrameLoadType::Reload
2779         && loadType != FrameLoadType::ReloadFromOrigin
2780         && loadType != FrameLoadType::Same
2781         && !shouldReload(m_frame.document()->url(), url)
2782         // We don't want to just scroll if a link from within a
2783         // frameset is trying to reload the frameset into _top.
2784         && !m_frame.document()->isFrameSet();
2785 }
2786
2787 void FrameLoader::scrollToFragmentWithParentBoundary(const URL& url)
2788 {
2789     FrameView* view = m_frame.view();
2790     if (!view)
2791         return;
2792
2793     // Leaking scroll position to a cross-origin ancestor would permit the so-called "framesniffing" attack.
2794     RefPtr<Frame> boundaryFrame(url.hasFragmentIdentifier() ? m_frame.document()->findUnsafeParentScrollPropagationBoundary() : 0);
2795
2796     if (boundaryFrame)
2797         boundaryFrame->view()->setSafeToPropagateScrollToParent(false);
2798
2799     view->scrollToFragment(url);
2800
2801     if (boundaryFrame)
2802         boundaryFrame->view()->setSafeToPropagateScrollToParent(true);
2803 }
2804
2805 bool FrameLoader::shouldClose()
2806 {
2807     Page* page = m_frame.page();
2808     if (!page)
2809         return true;
2810     if (!page->chrome().canRunBeforeUnloadConfirmPanel())
2811         return true;
2812
2813     // Store all references to each subframe in advance since beforeunload's event handler may modify frame
2814     Vector<Ref<Frame>, 16> targetFrames;
2815     targetFrames.append(m_frame);
2816     for (Frame* child = m_frame.tree().firstChild(); child; child = child->tree().traverseNext(&m_frame))
2817         targetFrames.append(*child);
2818
2819     bool shouldClose = false;
2820     {
2821         NavigationDisablerForBeforeUnload navigationDisabler;
2822         size_t i;
2823
2824         for (i = 0; i < targetFrames.size(); i++) {
2825             if (!targetFrames[i]->tree().isDescendantOf(&m_frame))
2826                 continue;
2827             if (!targetFrames[i]->loader().dispatchBeforeUnloadEvent(page->chrome(), this))
2828                 break;
2829         }
2830
2831         if (i == targetFrames.size())
2832             shouldClose = true;
2833     }
2834
2835     if (!shouldClose)
2836         m_submittedFormURL = URL();
2837
2838     m_currentNavigationHasShownBeforeUnloadConfirmPanel = false;
2839     return shouldClose;
2840 }
2841
2842 void FrameLoader::dispatchUnloadEvents(UnloadEventPolicy unloadEventPolicy)
2843 {
2844     if (!m_frame.document())
2845         return;
2846
2847     // We store the frame's page in a local variable because the frame might get detached inside dispatchEvent.
2848     ForbidPromptsScope forbidPrompts(m_frame.page());
2849
2850     if (m_didCallImplicitClose && !m_wasUnloadEventEmitted) {
2851         auto* currentFocusedElement = m_frame.document()->focusedElement();
2852         if (is<HTMLInputElement>(currentFocusedElement))
2853             downcast<HTMLInputElement>(*currentFocusedElement).endEditing();
2854         if (m_pageDismissalEventBeingDispatched == PageDismissalType::None) {
2855             if (unloadEventPolicy == UnloadEventPolicyUnloadAndPageHide) {
2856                 m_pageDismissalEventBeingDispatched = PageDismissalType::PageHide;
2857                 m_frame.document()->domWindow()->dispatchEvent(PageTransitionEvent::create(eventNames().pagehideEvent, m_frame.document()->inPageCache()), m_frame.document());
2858             }
2859
2860             // FIXME: update Page Visibility state here.
2861             // https://bugs.webkit.org/show_bug.cgi?id=116770
2862
2863             if (!m_frame.document()->inPageCache()) {
2864                 Ref<Event> unloadEvent(Event::create(eventNames().unloadEvent, false, false));
2865                 // The DocumentLoader (and thus its DocumentLoadTiming) might get destroyed
2866                 // while dispatching the event, so protect it to prevent writing the end
2867                 // time into freed memory.
2868                 RefPtr<DocumentLoader> documentLoader = m_provisionalDocumentLoader;
2869                 m_pageDismissalEventBeingDispatched = PageDismissalType::Unload;
2870                 if (documentLoader && documentLoader->timing().navigationStart() && !documentLoader->timing().unloadEventStart() && !documentLoader->timing().unloadEventEnd()) {
2871                     auto& timing = documentLoader->timing();
2872                     timing.markUnloadEventStart();
2873                     m_frame.document()->domWindow()->dispatchEvent(unloadEvent, m_frame.document());
2874                     timing.markUnloadEventEnd();
2875                 } else
2876                     m_frame.document()->domWindow()->dispatchEvent(unloadEvent, m_frame.document());
2877             }
2878         }
2879         m_pageDismissalEventBeingDispatched = PageDismissalType::None;
2880         if (m_frame.document())
2881             m_frame.document()->updateStyleIfNeeded();
2882         m_wasUnloadEventEmitted = true;
2883     }
2884
2885     // Dispatching the unload event could have made m_frame.document() null.
2886     if (!m_frame.document())
2887         return;
2888
2889     if (m_frame.document()->inPageCache())
2890         return;
2891
2892     // Don't remove event listeners from a transitional empty document (see bug 28716 for more information).
2893     bool keepEventListeners = m_stateMachine.isDisplayingInitialEmptyDocument() && m_provisionalDocumentLoader
2894         && m_frame.document()->isSecureTransitionTo(m_provisionalDocumentLoader->url());
2895
2896     if (!keepEventListeners)
2897         m_frame.document()->removeAllEventListeners();
2898 }
2899
2900 bool FrameLoader::dispatchBeforeUnloadEvent(Chrome& chrome, FrameLoader* frameLoaderBeingNavigated)
2901 {
2902     DOMWindow* domWindow = m_frame.document()->domWindow();
2903     if (!domWindow)
2904         return true;
2905
2906     RefPtr<Document> document = m_frame.document();
2907     if (!document->bodyOrFrameset())
2908         return true;
2909     
2910     Ref<BeforeUnloadEvent> beforeUnloadEvent = BeforeUnloadEvent::create();
2911     m_pageDismissalEventBeingDispatched = PageDismissalType::BeforeUnload;
2912
2913     {
2914         ForbidPromptsScope forbidPrompts(m_frame.page());
2915         domWindow->dispatchEvent(beforeUnloadEvent, domWindow->document());
2916     }
2917
2918     m_pageDismissalEventBeingDispatched = PageDismissalType::None;
2919
2920     if (!beforeUnloadEvent->defaultPrevented())
2921         document->defaultEventHandler(beforeUnloadEvent.ptr());
2922     if (beforeUnloadEvent->returnValue().isNull())
2923         return true;
2924
2925     // If the navigating FrameLoader has already shown a beforeunload confirmation panel for the current navigation attempt,
2926     // this frame is not allowed to cause another one to be shown.
2927     if (frameLoaderBeingNavigated->m_currentNavigationHasShownBeforeUnloadConfirmPanel) {
2928         document->addConsoleMessage(MessageSource::JS, MessageLevel::Error, ASCIILiteral("Blocked attempt to show multiple beforeunload confirmation dialogs for the same navigation."));
2929         return true;
2930     }
2931
2932     // We should only display the beforeunload dialog for an iframe if its SecurityOrigin matches all
2933     // ancestor frame SecurityOrigins up through the navigating FrameLoader.
2934     if (frameLoaderBeingNavigated != this) {
2935         Frame* parentFrame = m_frame.tree().parent();
2936         while (parentFrame) {
2937             Document* parentDocument = parentFrame->document();
2938             if (!parentDocument)
2939                 return true;
2940             if (!m_frame.document() || !m_frame.document()->securityOrigin()->canAccess(parentDocument->securityOrigin())) {
2941                 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."));
2942                 return true;
2943             }
2944             
2945             if (&parentFrame->loader() == frameLoaderBeingNavigated)
2946                 break;
2947             
2948             parentFrame = parentFrame->tree().parent();
2949         }
2950         
2951         // The navigatingFrameLoader should always be in our ancestory.
2952         ASSERT(parentFrame);
2953         ASSERT(&parentFrame->loader() == frameLoaderBeingNavigated);
2954     }
2955
2956     frameLoaderBeingNavigated->m_currentNavigationHasShownBeforeUnloadConfirmPanel = true;
2957
2958     String text = document->displayStringModifiedByEncoding(beforeUnloadEvent->returnValue());
2959     return chrome.runBeforeUnloadConfirmPanel(text, &m_frame);
2960 }
2961
2962 void FrameLoader::continueLoadAfterNavigationPolicy(const ResourceRequest& request, PassRefPtr<FormState> formState, bool shouldContinue, AllowNavigationToInvalidURL allowNavigationToInvalidURL)
2963 {
2964     // If we loaded an alternate page to replace an unreachableURL, we'll get in here with a
2965     // nil policyDataSource because loading the alternate page will have passed
2966     // through this method already, nested; otherwise, policyDataSource should still be set.
2967     ASSERT(m_policyDocumentLoader || !m_provisionalDocumentLoader->unreachableURL().isEmpty());
2968
2969     bool isTargetItem = history().provisionalItem() ? history().provisionalItem()->isTargetItem() : false;
2970
2971     bool urlIsDisallowed = allowNavigationToInvalidURL == AllowNavigationToInvalidURL::No && !request.url().isValid();
2972
2973     // Three reasons we can't continue:
2974     //    1) Navigation policy delegate said we can't so request is nil. A primary case of this 
2975     //       is the user responding Cancel to the form repost nag sheet.
2976     //    2) User responded Cancel to an alert popped up by the before unload event handler.
2977     //    3) The request's URL is invalid and navigation to invalid URLs is disallowed.
2978     bool canContinue = shouldContinue && shouldClose() && !urlIsDisallowed;
2979
2980     if (!canContinue) {
2981         // If we were waiting for a quick redirect, but the policy delegate decided to ignore it, then we 
2982         // need to report that the client redirect was cancelled.
2983         // FIXME: The client should be told about ignored non-quick redirects, too.
2984         if (m_quickRedirectComing)
2985             clientRedirectCancelledOrFinished(false);
2986
2987         setPolicyDocumentLoader(nullptr);
2988
2989         // If the navigation request came from the back/forward menu, and we punt on it, we have the 
2990         // problem that we have optimistically moved the b/f cursor already, so move it back.  For sanity, 
2991         // we only do this when punting a navigation for the target frame or top-level frame.  
2992         if ((isTargetItem || m_frame.isMainFrame()) && isBackForwardLoadType(policyChecker().loadType())) {
2993             if (Page* page = m_frame.page()) {
2994                 if (HistoryItem* resetItem = m_frame.mainFrame().loader().history().currentItem()) {
2995                     page->backForward().setCurrentItem(resetItem);
2996                     m_frame.loader().client().updateGlobalHistoryItemForPage();
2997                 }
2998             }
2999         }
3000         return;
3001     }
3002
3003     FrameLoadType type = policyChecker().loadType();
3004     // A new navigation is in progress, so don't clear the history's provisional item.
3005     stopAllLoaders(ShouldNotClearProvisionalItem);
3006     
3007     // <rdar://problem/6250856> - In certain circumstances on pages with multiple frames, stopAllLoaders()
3008     // might detach the current FrameLoader, in which case we should bail on this newly defunct load. 
3009     if (!m_frame.page())
3010         return;
3011
3012     setProvisionalDocumentLoader(m_policyDocumentLoader.get());
3013     m_loadType = type;
3014     setState(FrameStateProvisional);
3015
3016     setPolicyDocumentLoader(nullptr);
3017
3018     if (isBackForwardLoadType(type)) {
3019         auto& diagnosticLoggingClient = m_frame.mainFrame().diagnosticLoggingClient();
3020         if (history().provisionalItem()->isInPageCache()) {
3021             diagnosticLoggingClient.logDiagnosticMessageWithResult(DiagnosticLoggingKeys::pageCacheKey(), DiagnosticLoggingKeys::retrievalKey(), DiagnosticLoggingResultPass, ShouldSample::Yes);
3022             loadProvisionalItemFromCachedPage();
3023             return;
3024         }
3025         diagnosticLoggingClient.logDiagnosticMessageWithResult(DiagnosticLoggingKeys::pageCacheKey(), DiagnosticLoggingKeys::retrievalKey(), DiagnosticLoggingResultFail, ShouldSample::Yes);
3026     }
3027
3028     if (!formState) {
3029         continueLoadAfterWillSubmitForm();
3030         return;
3031     }
3032
3033     m_client.dispatchWillSubmitForm(formState, [this](PolicyAction action) {
3034         policyChecker().continueLoadAfterWillSubmitForm(action);
3035     });
3036 }
3037
3038 void FrameLoader::continueLoadAfterNewWindowPolicy(const ResourceRequest& request,
3039     PassRefPtr<FormState> formState, const String& frameName, const NavigationAction& action, bool shouldContinue, AllowNavigationToInvalidURL allowNavigationToInvalidURL, NewFrameOpenerPolicy openerPolicy)
3040 {
3041     if (!shouldContinue)
3042         return;
3043
3044     Ref<Frame> frame(m_frame);
3045     RefPtr<Frame> mainFrame = m_client.dispatchCreatePage(action);
3046     if (!mainFrame)
3047         return;
3048
3049     if (frameName != "_blank")
3050         mainFrame->tree().setName(frameName);
3051
3052     mainFrame->page()->setOpenedByDOM();
3053     mainFrame->loader().m_client.dispatchShow();
3054     if (openerPolicy == NewFrameOpenerPolicy::Allow) {
3055         mainFrame->loader().setOpener(frame.ptr());
3056         mainFrame->document()->setReferrerPolicy(frame->document()->referrerPolicy());
3057     }
3058
3059     NavigationAction newAction(request, action.shouldOpenExternalURLsPolicy());
3060     mainFrame->loader().loadWithNavigationAction(request, newAction, LockHistory::No, FrameLoadType::Standard, formState, allowNavigationToInvalidURL);
3061 }
3062
3063 void FrameLoader::requestFromDelegate(ResourceRequest& request, unsigned long& identifier, ResourceError& error)
3064 {
3065     ASSERT(!request.isNull());
3066
3067     identifier = 0;
3068     if (Page* page = m_frame.page()) {
3069         identifier = page->progress().createUniqueIdentifier();
3070         notifier().assignIdentifierToInitialRequest(identifier, m_documentLoader.get(), request);
3071     }
3072
3073     ResourceRequest newRequest(request);
3074     notifier().dispatchWillSendRequest(m_documentLoader.get(), identifier, newRequest, ResourceResponse());
3075
3076     if (newRequest.isNull())
3077         error = cancelledError(request);
3078     else
3079         error = ResourceError();
3080
3081     request = newRequest;
3082 }
3083
3084 void FrameLoader::loadedResourceFromMemoryCache(CachedResource* resource, ResourceRequest& newRequest)
3085 {
3086     Page* page = m_frame.page();
3087     if (!page)
3088         return;
3089
3090     if (!resource->shouldSendResourceLoadCallbacks() || m_documentLoader->haveToldClientAboutLoad(resource->url()))
3091         return;
3092
3093     // Main resource delegate messages are synthesized in MainResourceLoader, so we must not send them here.
3094     if (resource->type() == CachedResource::MainResource)
3095         return;
3096
3097     if (!page->areMemoryCacheClientCallsEnabled()) {
3098         InspectorInstrumentation::didLoadResourceFromMemoryCache(*page, m_documentLoader.get(), resource);
3099         m_documentLoader->recordMemoryCacheLoadForFutureClientNotification(resource->resourceRequest());
3100         m_documentLoader->didTellClientAboutLoad(resource->url());
3101         return;
3102     }
3103
3104     if (m_client.dispatchDidLoadResourceFromMemoryCache(m_documentLoader.get(), newRequest, resource->response(), resource->encodedSize())) {
3105         InspectorInstrumentation::didLoadResourceFromMemoryCache(*page, m_documentLoader.get(), resource);
3106         m_documentLoader->didTellClientAboutLoad(resource->url());
3107         return;
3108     }
3109
3110     unsigned long identifier;
3111     ResourceError error;
3112     requestFromDelegate(newRequest, identifier, error);
3113     InspectorInstrumentation::markResourceAsCached(*page, identifier);
3114     notifier().sendRemainingDelegateMessages(m_documentLoader.get(), identifier, newRequest, resource->response(), 0, resource->encodedSize(), 0, error);
3115 }
3116
3117 void FrameLoader::applyUserAgent(ResourceRequest& request)
3118 {
3119     String userAgent = this->userAgent(request.url());
3120     ASSERT(!userAgent.isNull());
3121     request.setHTTPUserAgent(userAgent);
3122 }
3123
3124 bool FrameLoader::shouldInterruptLoadForXFrameOptions(const String& content, const URL& url, unsigned long requestIdentifier)
3125 {
3126     Frame& topFrame = m_frame.tree().top();
3127     if (&m_frame == &topFrame)
3128         return false;
3129
3130     XFrameOptionsDisposition disposition = parseXFrameOptionsHeader(content);
3131
3132     switch (disposition) {
3133     case XFrameOptionsSameOrigin: {
3134         RefPtr<SecurityOrigin> origin = SecurityOrigin::create(url);
3135         if (!origin->isSameSchemeHostPort(topFrame.document()->securityOrigin()))
3136             return true;
3137         for (Frame* frame = m_frame.tree().parent(); frame; frame = frame->tree().parent()) {
3138             if (!origin->isSameSchemeHostPort(frame->document()->securityOrigin()))
3139                 break;
3140         }
3141         return false;
3142     }
3143     case XFrameOptionsDeny:
3144         return true;
3145     case XFrameOptionsAllowAll:
3146         return false;
3147     case XFrameOptionsConflict:
3148         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);
3149         return true;
3150     case XFrameOptionsInvalid:
3151         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);
3152         return false;
3153     case XFrameOptionsNone:
3154         return false;
3155     }
3156     ASSERT_NOT_REACHED();
3157     return false;
3158 }
3159
3160 void FrameLoader::loadProvisionalItemFromCachedPage()
3161 {
3162     DocumentLoader* provisionalLoader = provisionalDocumentLoader();
3163     LOG(PageCache, "WebCorePageCache: Loading provisional DocumentLoader %p with URL '%s' from CachedPage", provisionalDocumentLoader(), provisionalDocumentLoader()->url().stringCenterEllipsizedToLength().utf8().data());
3164
3165     prepareForLoadStart();
3166
3167     m_loadingFromCachedPage = true;
3168
3169     // Should have timing data from previous time(s) the page was shown.
3170     ASSERT(provisionalLoader->timing().navigationStart());
3171     provisionalLoader->resetTiming();
3172     provisionalLoader->timing().markNavigationStart();
3173
3174     provisionalLoader->setCommitted(true);
3175     commitProvisionalLoad();
3176 }
3177
3178 bool FrameLoader::shouldTreatURLAsSameAsCurrent(const URL& url) const
3179 {
3180     if (!history().currentItem())
3181         return false;
3182     return url == history().currentItem()->url() || url == history().currentItem()->originalURL();
3183 }
3184
3185 bool FrameLoader::shouldTreatURLAsSrcdocDocument(const URL& url) const
3186 {
3187     if (!equalIgnoringCase(url.string(), "about:srcdoc"))
3188         return false;
3189     HTMLFrameOwnerElement* ownerElement = m_frame.ownerElement();
3190     if (!ownerElement)
3191         return false;
3192     if (!ownerElement->hasTagName(iframeTag))
3193         return false;
3194     return ownerElement->fastHasAttribute(srcdocAttr);
3195 }
3196
3197 Frame* FrameLoader::findFrameForNavigation(const AtomicString& name, Document* activeDocument)
3198 {
3199     Frame* frame = m_frame.tree().find(name);
3200
3201     // FIXME: Eventually all callers should supply the actual activeDocument so we can call canNavigate with the right document.
3202     if (!activeDocument)
3203         activeDocument = m_frame.document();
3204
3205     if (!activeDocument->canNavigate(frame))
3206         return nullptr;
3207
3208     return frame;
3209 }
3210
3211 void FrameLoader::loadSameDocumentItem(HistoryItem& item)
3212 {
3213     ASSERT(item.documentSequenceNumber() == history().currentItem()->documentSequenceNumber());
3214
3215     // Save user view state to the current history item here since we don't do a normal load.
3216     // FIXME: Does form state need to be saved here too?
3217     history().saveScrollPositionAndViewStateToItem(history().currentItem());
3218     if (FrameView* view = m_frame.view())
3219         view->setWasScrolledByUser(false);
3220
3221     history().setCurrentItem(&item);
3222         
3223     // loadInSameDocument() actually changes the URL and notifies load delegates of a "fake" load
3224     loadInSameDocument(item.url(), item.stateObject(), false);
3225
3226     // Restore user view state from the current history item here since we don't do a normal load.
3227     history().restoreScrollPositionAndViewState();
3228 }
3229
3230 // FIXME: This function should really be split into a couple pieces, some of
3231 // which should be methods of HistoryController and some of which should be
3232 // methods of FrameLoader.
3233 void FrameLoader::loadDifferentDocumentItem(HistoryItem& item, FrameLoadType loadType, FormSubmissionCacheLoadPolicy cacheLoadPolicy)
3234 {
3235     // Remember this item so we can traverse any child items as child frames load
3236     history().setProvisionalItem(&item);
3237
3238     if (CachedPage* cachedPage = PageCache::singleton().get(item, m_frame.page())) {
3239         auto documentLoader = cachedPage->documentLoader();
3240         m_client.updateCachedDocumentLoader(*documentLoader);
3241         documentLoader->setTriggeringAction(NavigationAction(documentLoader->request(), loadType, false));
3242         documentLoader->setLastCheckedRequest(ResourceRequest());
3243         loadWithDocumentLoader(documentLoader, loadType, 0, AllowNavigationToInvalidURL::Yes);
3244         return;
3245     }
3246
3247     URL itemURL = item.url();
3248     URL itemOriginalURL = item.originalURL();
3249     URL currentURL;
3250     if (documentLoader())
3251         currentURL = documentLoader()->url();
3252     RefPtr<FormData> formData = item.formData();
3253
3254     ResourceRequest request(itemURL);
3255
3256     if (!item.referrer().isNull())
3257         request.setHTTPReferrer(item.referrer());
3258
3259     ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy = shouldOpenExternalURLsPolicyToApply(m_frame, item.shouldOpenExternalURLsPolicy());
3260     bool isFormSubmission = false;
3261     Event* event = nullptr;
3262
3263     // If this was a repost that failed the page cache, we might try to repost the form.
3264     NavigationAction action;
3265     if (formData) {
3266         formData->generateFiles(m_frame.document());
3267
3268         request.setHTTPMethod("POST");
3269         request.setHTTPBody(formData);
3270         request.setHTTPContentType(item.formContentType());
3271         RefPtr<SecurityOrigin> securityOrigin = SecurityOrigin::createFromString(item.referrer());
3272         addHTTPOriginIfNeeded(request, securityOrigin->toString());
3273
3274         // Make sure to add extra fields to the request after the Origin header is added for the FormData case.
3275         // See https://bugs.webkit.org/show_bug.cgi?id=22194 for more discussion.
3276         addExtraFieldsToRequest(request, loadType, true);
3277         
3278         // FIXME: Slight hack to test if the NSURL cache contains the page we're going to.
3279         // We want to know this before talking to the policy delegate, since it affects whether 
3280         // we show the DoYouReallyWantToRepost nag.
3281         //
3282         // This trick has a small bug (3123893) where we might find a cache hit, but then
3283         // have the item vanish when we try to use it in the ensuing nav.  This should be
3284         // extremely rare, but in that case the user will get an error on the navigation.
3285         
3286         if (cacheLoadPolicy == MayAttemptCacheOnlyLoadForFormSubmissionItem) {
3287             request.setCachePolicy(ReturnCacheDataDontLoad);
3288             action = NavigationAction(request, loadType, isFormSubmission, event, shouldOpenExternalURLsPolicy);
3289         } else {
3290             request.setCachePolicy(ReturnCacheDataElseLoad);
3291             action = NavigationAction(request, NavigationType::FormResubmitted, event, shouldOpenExternalURLsPolicy);
3292         }
3293     } else {
3294         switch (loadType) {
3295         case FrameLoadType::Reload:
3296         case FrameLoadType::ReloadFromOrigin:
3297             request.setCachePolicy(ReloadIgnoringCacheData);
3298             break;
3299         case FrameLoadType::Back:
3300         case FrameLoadType::Forward:
3301         case FrameLoadType::IndexedBackForward:
3302             request.setCachePolicy(ReturnCacheDataElseLoad);
3303             break;
3304         case FrameLoadType::Standard:
3305         case FrameLoadType::RedirectWithLockedBackForwardList:
3306             break;
3307         case FrameLoadType::Same:
3308         default:
3309             ASSERT_NOT_REACHED();
3310         }
3311
3312         addExtraFieldsToRequest(request, loadType, true);
3313
3314         ResourceRequest requestForOriginalURL(request);
3315         requestForOriginalURL.setURL(itemOriginalURL);
3316         action = NavigationAction(requestForOriginalURL, loadType, isFormSubmission, event, shouldOpenExternalURLsPolicy);
3317     }
3318
3319     loadWithNavigationAction(request, action, LockHistory::No, loadType, 0, AllowNavigationToInvalidURL::Yes);
3320 }
3321
3322 // Loads content into this frame, as specified by history item
3323 void FrameLoader::loadItem(HistoryItem& item, FrameLoadType loadType)
3324 {
3325     m_requestedHistoryItem = &item;
3326     HistoryItem* currentItem = history().currentItem();
3327     bool sameDocumentNavigation = currentItem && item.shouldDoSameDocumentNavigationTo(*currentItem);
3328
3329     if (sameDocumentNavigation)
3330         loadSameDocumentItem(item);
3331     else
3332         loadDifferentDocumentItem(item, loadType, MayAttemptCacheOnlyLoadForFormSubmissionItem);
3333 }
3334
3335 void FrameLoader::retryAfterFailedCacheOnlyMainResourceLoad()
3336 {
3337     ASSERT(m_state == FrameStateProvisional);
3338     ASSERT(!m_loadingFromCachedPage);
3339     ASSERT(history().provisionalItem());
3340     ASSERT(history().provisionalItem()->formData());
3341     ASSERT(history().provisionalItem() == m_requestedHistoryItem.get());
3342
3343     FrameLoadType loadType = m_loadType;
3344     HistoryItem& item = *history().provisionalItem();
3345
3346     stopAllLoaders(ShouldNotClearProvisionalItem);
3347     loadDifferentDocumentItem(item, loadType, MayNotAttemptCacheOnlyLoadForFormSubmissionItem);
3348 }
3349
3350 ResourceError FrameLoader::cancelledError(const ResourceRequest& request) const
3351 {
3352     ResourceError error = m_client.cancelledError(request);
3353     error.setIsCancellation(true);
3354     return error;
3355 }
3356
3357 ResourceError FrameLoader::blockedByContentBlockerError(const ResourceRequest& request) const
3358 {
3359     return m_client.blockedByContentBlockerError(request);
3360 }
3361
3362 #if PLATFORM(IOS)
3363 RetainPtr<CFDictionaryRef> FrameLoader::connectionProperties(ResourceLoader* loader)
3364 {
3365     return m_client.connectionProperties(loader->documentLoader(), loader->identifier());
3366 }
3367 #endif
3368
3369 String FrameLoader::referrer() const
3370 {
3371     return m_documentLoader ? m_documentLoader->request().httpReferrer() : "";
3372 }
3373
3374 void FrameLoader::dispatchDidClearWindowObjectsInAllWorlds()
3375 {
3376     if (!m_frame.script().canExecuteScripts(NotAboutToExecuteScript))
3377         return;
3378
3379     Vector<Ref<DOMWrapperWorld>> worlds;
3380     ScriptController::getAllWorlds(worlds);
3381     for (auto& world : worlds)
3382         dispatchDidClearWindowObjectInWorld(world);
3383 }
3384
3385 void FrameLoader::dispatchDidClearWindowObjectInWorld(DOMWrapperWorld& world)
3386 {
3387     if (!m_frame.script().canExecuteScripts(NotAboutToExecuteScript) || !m_frame.script().existingWindowShell(world))
3388         return;
3389
3390     m_client.dispatchDidClearWindowObjectInWorld(world);
3391
3392     if (Page* page = m_frame.page())
3393         page->inspectorController().didClearWindowObjectInWorld(m_frame, world);
3394
3395     InspectorInstrumentation::didClearWindowObjectInWorld(m_frame, world);
3396 }
3397
3398 void FrameLoader::dispatchGlobalObjectAvailableInAllWorlds()
3399 {
3400     Vector<Ref<DOMWrapperWorld>> worlds;
3401     ScriptController::getAllWorlds(worlds);
3402     for (auto& world : worlds)
3403         m_client.dispatchGlobalObjectAvailable(world);
3404 }
3405
3406 SandboxFlags FrameLoader::effectiveSandboxFlags() const
3407 {
3408     SandboxFlags flags = m_forcedSandboxFlags;
3409     if (Frame* parentFrame = m_frame.tree().parent())
3410         flags |= parentFrame->document()->sandboxFlags();
3411     if (HTMLFrameOwnerElement* ownerElement = m_frame.ownerElement())
3412         flags |= ownerElement->sandboxFlags();
3413     return flags;
3414 }
3415
3416 void FrameLoader::didChangeTitle(DocumentLoader* loader)
3417 {
3418     m_client.didChangeTitle(loader);
3419
3420     if (loader == m_documentLoader) {
3421         // Must update the entries in the back-forward list too.
3422         history().setCurrentItemTitle(loader->title());
3423         // This must go through the WebFrame because it has the right notion of the current b/f item.
3424         m_client.setTitle(loader->title(), loader->urlForHistory());
3425         m_client.setMainFrameDocumentReady(true); // update observers with new DOMDocument
3426         m_client.dispatchDidReceiveTitle(loader->title());
3427     }
3428
3429 #if ENABLE(REMOTE_INSPECTOR)
3430     if (m_frame.isMainFrame())
3431         m_frame.page()->remoteInspectorInformationDidChange();
3432 #endif
3433 }
3434
3435 void FrameLoader::dispatchDidCommitLoad()
3436 {
3437     if (m_stateMachine.creatingInitialEmptyDocument())
3438         return;
3439
3440     m_client.dispatchDidCommitLoad();
3441
3442     if (m_frame.isMainFrame()) {
3443         m_frame.page()->resetSeenPlugins();
3444         m_frame.page()->resetSeenMediaEngines();