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