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