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