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