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