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