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