20e89125b3b2270d289601a43fcbdb98b3316fd7
[WebKit-https.git] / WebCore / loader / FrameLoader.cpp
1 /*
2  * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
3  * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
4  * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1.  Redistributions of source code must retain the above copyright
11  *     notice, this list of conditions and the following disclaimer. 
12  * 2.  Redistributions in binary form must reproduce the above copyright
13  *     notice, this list of conditions and the following disclaimer in the
14  *     documentation and/or other materials provided with the distribution. 
15  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
16  *     its contributors may be used to endorse or promote products derived
17  *     from this software without specific prior written permission. 
18  *
19  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
20  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
23  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include "config.h"
32 #include "FrameLoader.h"
33
34 #include "Archive.h"
35 #include "ArchiveFactory.h"
36 #include "CString.h"
37 #include "Cache.h"
38 #include "CachedPage.h"
39 #include "Chrome.h"
40 #include "DOMImplementation.h"
41 #include "DOMWindow.h"
42 #include "DocLoader.h"
43 #include "Document.h"
44 #include "DocumentLoader.h"
45 #include "Editor.h"
46 #include "EditorClient.h"
47 #include "Element.h"
48 #include "Event.h"
49 #include "EventNames.h"
50 #include "FloatRect.h"
51 #include "FormState.h"
52 #include "Frame.h"
53 #include "FrameLoadRequest.h"
54 #include "FrameLoaderClient.h"
55 #include "FrameTree.h"
56 #include "FrameView.h"
57 #include "HTMLAnchorElement.h"
58 #include "HTMLFormElement.h"
59 #include "HTMLFrameElement.h"
60 #include "HTMLNames.h"
61 #include "HTMLObjectElement.h"
62 #include "HTTPParsers.h"
63 #include "HistoryItem.h"
64 #include "IconDatabase.h"
65 #include "IconLoader.h"
66 #include "InspectorController.h"
67 #include "Logging.h"
68 #include "MIMETypeRegistry.h"
69 #include "MainResourceLoader.h"
70 #include "Page.h"
71 #include "PageCache.h"
72 #include "PageGroup.h"
73 #include "PluginData.h"
74 #include "PluginDocument.h"
75 #include "ProgressTracker.h"
76 #include "RenderPart.h"
77 #include "RenderView.h"
78 #include "RenderWidget.h"
79 #include "ResourceHandle.h"
80 #include "ResourceRequest.h"
81 #include "ScriptController.h"
82 #include "ScriptSourceCode.h"
83 #include "ScriptValue.h"
84 #include "SecurityOrigin.h"
85 #include "SegmentedString.h"
86 #include "Settings.h"
87 #include "TextResourceDecoder.h"
88 #include "WindowFeatures.h"
89 #include "XMLHttpRequest.h"
90 #include "XMLTokenizer.h"
91 #include <wtf/CurrentTime.h>
92 #include <wtf/StdLibExtras.h>
93
94 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
95 #include "ApplicationCache.h"
96 #include "ApplicationCacheResource.h"
97 #endif
98
99 #if ENABLE(SVG)
100 #include "SVGDocument.h"
101 #include "SVGLocatable.h"
102 #include "SVGNames.h"
103 #include "SVGPreserveAspectRatio.h"
104 #include "SVGSVGElement.h"
105 #include "SVGViewElement.h"
106 #include "SVGViewSpec.h"
107 #endif
108
109 namespace WebCore {
110
111 #if ENABLE(SVG)
112 using namespace SVGNames;
113 #endif
114 using namespace HTMLNames;
115
116 typedef HashSet<String, CaseFoldingHash> LocalSchemesMap;
117
118 struct FormSubmission {
119     FormSubmission(const char* action, const String& url, PassRefPtr<FormData> formData,
120                    const String& target, const String& contentType, const String& boundary,
121                    PassRefPtr<Event> event, bool lockHistory, bool lockBackForwardList)
122         : action(action)
123         , url(url)
124         , formData(formData)
125         , target(target)
126         , contentType(contentType)
127         , boundary(boundary)
128         , event(event)
129         , lockHistory(lockHistory)
130         , lockBackForwardList(lockBackForwardList)
131     {
132     }
133
134     const char* action;
135     String url;
136     RefPtr<FormData> formData;
137     String target;
138     String contentType;
139     String boundary;
140     RefPtr<Event> event;
141     bool lockHistory;
142     bool lockBackForwardList;
143 };
144
145 struct ScheduledRedirection {
146     enum Type { redirection, locationChange, historyNavigation, locationChangeDuringLoad };
147     Type type;
148     double delay;
149     String url;
150     String referrer;
151     int historySteps;
152     bool lockHistory;
153     bool lockBackForwardList;
154     bool wasUserGesture;
155     bool wasRefresh;
156
157     ScheduledRedirection(double delay, const String& url, bool lockHistory, bool lockBackForwardList, bool wasUserGesture, bool refresh)
158         : type(redirection)
159         , delay(delay)
160         , url(url)
161         , historySteps(0)
162         , lockHistory(lockHistory)
163         , lockBackForwardList(lockBackForwardList)
164         , wasUserGesture(wasUserGesture)
165         , wasRefresh(refresh)
166     {
167     }
168
169     ScheduledRedirection(Type locationChangeType, const String& url, const String& referrer, bool lockHistory, bool lockBackForwardList, bool wasUserGesture, bool refresh)
170         : type(locationChangeType)
171         , delay(0)
172         , url(url)
173         , referrer(referrer)
174         , historySteps(0)
175         , lockHistory(lockHistory)
176         , lockBackForwardList(lockBackForwardList)
177         , wasUserGesture(wasUserGesture)
178         , wasRefresh(refresh)
179     {
180     }
181
182     explicit ScheduledRedirection(int historyNavigationSteps)
183         : type(historyNavigation)
184         , delay(0)
185         , historySteps(historyNavigationSteps)
186         , lockHistory(false)
187         , wasUserGesture(false)
188         , wasRefresh(false)
189     {
190     }
191 };
192
193 static double storedTimeOfLastCompletedLoad;
194 static FrameLoader::LocalLoadPolicy localLoadPolicy = FrameLoader::AllowLocalLoadsForLocalOnly;
195
196 bool isBackForwardLoadType(FrameLoadType type)
197 {
198     switch (type) {
199         case FrameLoadTypeStandard:
200         case FrameLoadTypeReload:
201         case FrameLoadTypeReloadFromOrigin:
202         case FrameLoadTypeSame:
203         case FrameLoadTypeRedirectWithLockedBackForwardList:
204         case FrameLoadTypeReplace:
205             return false;
206         case FrameLoadTypeBack:
207         case FrameLoadTypeForward:
208         case FrameLoadTypeIndexedBackForward:
209             return true;
210     }
211     ASSERT_NOT_REACHED();
212     return false;
213 }
214
215 static int numRequests(Document* document)
216 {
217     if (!document)
218         return 0;
219     
220     return document->docLoader()->requestCount();
221 }
222
223 FrameLoader::FrameLoader(Frame* frame, FrameLoaderClient* client)
224     : m_frame(frame)
225     , m_client(client)
226     , m_state(FrameStateCommittedPage)
227     , m_loadType(FrameLoadTypeStandard)
228     , m_policyLoadType(FrameLoadTypeStandard)
229     , m_delegateIsHandlingProvisionalLoadError(false)
230     , m_delegateIsDecidingNavigationPolicy(false)
231     , m_delegateIsHandlingUnimplementablePolicy(false)
232     , m_firstLayoutDone(false)
233     , m_quickRedirectComing(false)
234     , m_sentRedirectNotification(false)
235     , m_inStopAllLoaders(false)
236     , m_navigationDuringLoad(false)
237     , m_isExecutingJavaScriptFormAction(false)
238     , m_isRunningScript(false)
239     , m_didCallImplicitClose(false)
240     , m_wasUnloadEventEmitted(false)
241     , m_isComplete(false)
242     , m_isLoadingMainResource(false)
243     , m_cancellingWithLoadInProgress(false)
244     , m_needsClear(false)
245     , m_receivedData(false)
246     , m_encodingWasChosenByUser(false)
247     , m_containsPlugIns(false)
248     , m_redirectionTimer(this, &FrameLoader::redirectionTimerFired)
249     , m_checkCompletedTimer(this, &FrameLoader::checkCompletedTimerFired)
250     , m_checkLoadCompleteTimer(this, &FrameLoader::checkLoadCompleteTimerFired)
251     , m_opener(0)
252     , m_openedByDOM(false)
253     , m_creatingInitialEmptyDocument(false)
254     , m_isDisplayingInitialEmptyDocument(false)
255     , m_committedFirstRealDocumentLoad(false)
256     , m_didPerformFirstNavigation(false)
257 #ifndef NDEBUG
258     , m_didDispatchDidCommitLoad(false)
259 #endif
260 #if ENABLE(WML)
261     , m_forceReloadWmlDeck(false)
262 #endif
263 {
264 }
265
266 FrameLoader::~FrameLoader()
267 {
268     setOpener(0);
269
270     HashSet<Frame*>::iterator end = m_openedFrames.end();
271     for (HashSet<Frame*>::iterator it = m_openedFrames.begin(); it != end; ++it)
272         (*it)->loader()->m_opener = 0;
273         
274     m_client->frameLoaderDestroyed();
275 }
276
277 void FrameLoader::init()
278 {
279     // this somewhat odd set of steps is needed to give the frame an initial empty document
280     m_isDisplayingInitialEmptyDocument = false;
281     m_creatingInitialEmptyDocument = true;
282     setPolicyDocumentLoader(m_client->createDocumentLoader(ResourceRequest(KURL("")), SubstituteData()).get());
283     setProvisionalDocumentLoader(m_policyDocumentLoader.get());
284     setState(FrameStateProvisional);
285     m_provisionalDocumentLoader->setResponse(ResourceResponse(KURL(), "text/html", 0, String(), String()));
286     m_provisionalDocumentLoader->finishedLoading();
287     begin(KURL(), false);
288     end();
289     m_frame->document()->cancelParsing();
290     m_creatingInitialEmptyDocument = false;
291     m_didCallImplicitClose = true;
292 }
293
294 void FrameLoader::setDefersLoading(bool defers)
295 {
296     if (m_documentLoader)
297         m_documentLoader->setDefersLoading(defers);
298     if (m_provisionalDocumentLoader)
299         m_provisionalDocumentLoader->setDefersLoading(defers);
300     if (m_policyDocumentLoader)
301         m_policyDocumentLoader->setDefersLoading(defers);
302 }
303
304 Frame* FrameLoader::createWindow(FrameLoader* frameLoaderForFrameLookup, const FrameLoadRequest& request, const WindowFeatures& features, bool& created)
305
306     ASSERT(!features.dialog || request.frameName().isEmpty());
307
308     if (!request.frameName().isEmpty() && request.frameName() != "_blank") {
309         Frame* frame = frameLoaderForFrameLookup->frame()->tree()->find(request.frameName());
310         if (frame && shouldAllowNavigation(frame)) {
311             if (!request.resourceRequest().url().isEmpty())
312                 frame->loader()->loadFrameRequestWithFormAndValues(request, false, false, 0, 0, HashMap<String, String>());
313             if (Page* page = frame->page())
314                 page->chrome()->focus();
315             created = false;
316             return frame;
317         }
318     }
319     
320     // FIXME: Setting the referrer should be the caller's responsibility.
321     FrameLoadRequest requestWithReferrer = request;
322     requestWithReferrer.resourceRequest().setHTTPReferrer(m_outgoingReferrer);
323     addHTTPOriginIfNeeded(requestWithReferrer.resourceRequest(), outgoingOrigin());
324
325     Page* oldPage = m_frame->page();
326     if (!oldPage)
327         return 0;
328         
329     Page* page = oldPage->chrome()->createWindow(m_frame, requestWithReferrer, features);
330     if (!page)
331         return 0;
332
333     Frame* frame = page->mainFrame();
334     if (request.frameName() != "_blank")
335         frame->tree()->setName(request.frameName());
336
337     page->chrome()->setToolbarsVisible(features.toolBarVisible || features.locationBarVisible);
338     page->chrome()->setStatusbarVisible(features.statusBarVisible);
339     page->chrome()->setScrollbarsVisible(features.scrollbarsVisible);
340     page->chrome()->setMenubarVisible(features.menuBarVisible);
341     page->chrome()->setResizable(features.resizable);
342
343     // 'x' and 'y' specify the location of the window, while 'width' and 'height' 
344     // specify the size of the page. We can only resize the window, so 
345     // adjust for the difference between the window size and the page size.
346
347     FloatRect windowRect = page->chrome()->windowRect();
348     FloatSize pageSize = page->chrome()->pageRect().size();
349     if (features.xSet)
350         windowRect.setX(features.x);
351     if (features.ySet)
352         windowRect.setY(features.y);
353     if (features.widthSet)
354         windowRect.setWidth(features.width + (windowRect.width() - pageSize.width()));
355     if (features.heightSet)
356         windowRect.setHeight(features.height + (windowRect.height() - pageSize.height()));
357     page->chrome()->setWindowRect(windowRect);
358
359     page->chrome()->show();
360
361     created = true;
362     return frame;
363 }
364
365 bool FrameLoader::canHandleRequest(const ResourceRequest& request)
366 {
367     return m_client->canHandleRequest(request);
368 }
369
370 void FrameLoader::changeLocation(const String& url, const String& referrer, bool lockHistory, bool lockBackForwardList, bool userGesture, bool refresh)
371 {
372     changeLocation(completeURL(url), referrer, lockHistory, lockBackForwardList, userGesture, refresh);
373 }
374
375
376 void FrameLoader::changeLocation(const KURL& url, const String& referrer, bool lockHistory, bool lockBackForwardList, bool userGesture, bool refresh)
377 {
378     RefPtr<Frame> protect(m_frame);
379
380     ResourceRequest request(url, referrer, refresh ? ReloadIgnoringCacheData : UseProtocolCachePolicy);
381     
382     if (executeIfJavaScriptURL(request.url(), userGesture))
383         return;
384
385     urlSelected(request, "_self", 0, lockHistory, lockBackForwardList, userGesture);
386 }
387
388 void FrameLoader::urlSelected(const FrameLoadRequest& request, Event* event, bool lockHistory, bool lockBackForwardList)
389 {
390     FrameLoadRequest copy = request;
391     if (copy.resourceRequest().httpReferrer().isEmpty())
392         copy.resourceRequest().setHTTPReferrer(m_outgoingReferrer);
393     addHTTPOriginIfNeeded(copy.resourceRequest(), outgoingOrigin());
394
395     loadFrameRequestWithFormAndValues(copy, lockHistory, lockBackForwardList, event, 0, HashMap<String, String>());
396 }
397     
398 void FrameLoader::urlSelected(const ResourceRequest& request, const String& _target, Event* triggeringEvent, bool lockHistory, bool lockBackForwardList, bool userGesture)
399 {
400     if (executeIfJavaScriptURL(request.url(), userGesture, false))
401         return;
402
403     String target = _target;
404     if (target.isEmpty())
405         target = m_frame->document()->baseTarget();
406
407     FrameLoadRequest frameRequest(request, target);
408
409     urlSelected(frameRequest, triggeringEvent, lockHistory, lockBackForwardList);
410 }
411
412 bool FrameLoader::requestFrame(HTMLFrameOwnerElement* ownerElement, const String& urlString, const AtomicString& frameName)
413 {
414     // Support for <frame src="javascript:string">
415     KURL scriptURL;
416     KURL url;
417     if (protocolIs(urlString, "javascript")) {
418         scriptURL = completeURL(urlString); // completeURL() encodes the URL.
419         url = blankURL();
420     } else
421         url = completeURL(urlString);
422
423     Frame* frame = ownerElement->contentFrame();
424     if (frame)
425         frame->loader()->scheduleLocationChange(url.string(), m_outgoingReferrer, true, true, userGestureHint());
426     else
427         frame = loadSubframe(ownerElement, url, frameName, m_outgoingReferrer);
428     
429     if (!frame)
430         return false;
431
432     if (!scriptURL.isEmpty())
433         frame->loader()->executeIfJavaScriptURL(scriptURL);
434
435     return true;
436 }
437
438 Frame* FrameLoader::loadSubframe(HTMLFrameOwnerElement* ownerElement, const KURL& url, const String& name, const String& referrer)
439 {
440     bool allowsScrolling = true;
441     int marginWidth = -1;
442     int marginHeight = -1;
443     if (ownerElement->hasTagName(frameTag) || ownerElement->hasTagName(iframeTag)) {
444         HTMLFrameElementBase* o = static_cast<HTMLFrameElementBase*>(ownerElement);
445         allowsScrolling = o->scrollingMode() != ScrollbarAlwaysOff;
446         marginWidth = o->getMarginWidth();
447         marginHeight = o->getMarginHeight();
448     }
449
450     if (!canLoad(url, referrer)) {
451         FrameLoader::reportLocalLoadFailed(m_frame, url.string());
452         return 0;
453     }
454
455     bool hideReferrer = shouldHideReferrer(url, referrer);
456     RefPtr<Frame> frame = m_client->createFrame(url, name, ownerElement, hideReferrer ? String() : referrer,
457                                          allowsScrolling, marginWidth, marginHeight);
458
459     if (!frame)  {
460         checkCallImplicitClose();
461         return 0;
462     }
463     
464     frame->loader()->m_isComplete = false;
465    
466     RenderObject* renderer = ownerElement->renderer();
467     FrameView* view = frame->view();
468     if (renderer && renderer->isWidget() && view)
469         static_cast<RenderWidget*>(renderer)->setWidget(view);
470     
471     checkCallImplicitClose();
472     
473     // In these cases, the synchronous load would have finished
474     // before we could connect the signals, so make sure to send the 
475     // completed() signal for the child by hand
476     // FIXME: In this case the Frame will have finished loading before 
477     // it's being added to the child list. It would be a good idea to
478     // create the child first, then invoke the loader separately.
479     if (url.isEmpty() || url == blankURL()) {
480         frame->loader()->completed();
481         frame->loader()->checkCompleted();
482     }
483
484     return frame.get();
485 }
486
487 void FrameLoader::submitFormAgain()
488 {
489     if (m_isRunningScript)
490         return;
491     OwnPtr<FormSubmission> form(m_deferredFormSubmission.release());
492     if (!form)
493         return;
494     submitForm(form->action, form->url, form->formData, form->target, form->contentType, form->boundary, form->event.get(), form->lockHistory, form->lockBackForwardList);
495 }
496
497 void FrameLoader::submitForm(const char* action, const String& url, PassRefPtr<FormData> formData,
498     const String& target, const String& contentType, const String& boundary, Event* event, bool lockHistory, bool lockBackForwardList)
499 {
500     ASSERT(formData);
501     
502     if (!m_frame->page())
503         return;
504     
505     KURL u = completeURL(url.isNull() ? "" : url);
506     // FIXME: Do we really need to special-case an empty URL?
507     // Would it be better to just go on with the form submisson and let the I/O fail?
508     if (u.isEmpty())
509         return;
510
511     if (u.protocolIs("javascript")) {
512         m_isExecutingJavaScriptFormAction = true;
513         executeIfJavaScriptURL(u, false, false);
514         m_isExecutingJavaScriptFormAction = false;
515         return;
516     }
517
518     if (m_isRunningScript) {
519         if (m_deferredFormSubmission)
520             return;
521         m_deferredFormSubmission.set(new FormSubmission(action, url, formData, target, contentType, boundary, event, lockHistory, lockBackForwardList));
522         return;
523     }
524
525     formData->generateFiles(m_frame->page()->chrome()->client());
526     
527     FrameLoadRequest frameRequest;
528
529     if (!m_outgoingReferrer.isEmpty())
530         frameRequest.resourceRequest().setHTTPReferrer(m_outgoingReferrer);
531
532     frameRequest.setFrameName(target.isEmpty() ? m_frame->document()->baseTarget() : target);
533
534     // Handle mailto: forms
535     bool isMailtoForm = equalIgnoringCase(u.protocol(), "mailto");
536     if (isMailtoForm && strcmp(action, "GET") != 0) {
537         // Append body= for POST mailto, replace the whole query string for GET one.
538         String body = formData->flattenToString();
539         String query = u.query();
540         if (!query.isEmpty())
541             query.append('&');
542         u.setQuery(query + body);
543     }
544
545     if (strcmp(action, "GET") == 0) {
546         u.setQuery(formData->flattenToString());
547     } else {
548         if (!isMailtoForm)
549             frameRequest.resourceRequest().setHTTPBody(formData.get());
550         frameRequest.resourceRequest().setHTTPMethod("POST");
551
552         // construct some user headers if necessary
553         if (contentType.isNull() || contentType == "application/x-www-form-urlencoded")
554             frameRequest.resourceRequest().setHTTPContentType(contentType);
555         else // contentType must be "multipart/form-data"
556             frameRequest.resourceRequest().setHTTPContentType(contentType + "; boundary=" + boundary);
557     }
558
559     frameRequest.resourceRequest().setURL(u);
560     addHTTPOriginIfNeeded(frameRequest.resourceRequest(), outgoingOrigin());
561
562     submitForm(frameRequest, event, lockHistory, lockBackForwardList);
563 }
564
565 void FrameLoader::stopLoading(bool sendUnload)
566 {
567     if (m_frame->document() && m_frame->document()->tokenizer())
568         m_frame->document()->tokenizer()->stopParsing();
569
570     if (sendUnload) {
571         if (m_frame->document()) {
572             if (m_didCallImplicitClose && !m_wasUnloadEventEmitted) {
573                 Node* currentFocusedNode = m_frame->document()->focusedNode();
574                 if (currentFocusedNode)
575                     currentFocusedNode->aboutToUnload();
576                 m_frame->document()->dispatchWindowEvent(eventNames().unloadEvent, false, false);
577                 if (m_frame->document())
578                     m_frame->document()->updateRendering();
579                 m_wasUnloadEventEmitted = true;
580                 if (m_frame->eventHandler()->pendingFrameUnloadEventCount())
581                     m_frame->eventHandler()->clearPendingFrameUnloadEventCount();
582                 if (m_frame->eventHandler()->pendingFrameBeforeUnloadEventCount())
583                     m_frame->eventHandler()->clearPendingFrameBeforeUnloadEventCount();
584             }
585         }
586         if (m_frame->document() && !m_frame->document()->inPageCache())
587             m_frame->document()->removeAllEventListenersFromAllNodes();
588     }
589
590     m_isComplete = true; // to avoid calling completed() in finishedParsing() (David)
591     m_isLoadingMainResource = false;
592     m_didCallImplicitClose = true; // don't want that one either
593
594     if (m_frame->document() && m_frame->document()->parsing()) {
595         finishedParsing();
596         m_frame->document()->setParsing(false);
597     }
598   
599     m_workingURL = KURL();
600
601     if (Document* doc = m_frame->document()) {
602         if (DocLoader* docLoader = doc->docLoader())
603             cache()->loader()->cancelRequests(docLoader);
604
605 #if ENABLE(DATABASE)
606         doc->stopDatabases();
607 #endif
608     }
609
610     // tell all subframes to stop as well
611     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
612         child->loader()->stopLoading(sendUnload);
613
614     cancelRedirection();
615 }
616
617 void FrameLoader::stop()
618 {
619     // http://bugs.webkit.org/show_bug.cgi?id=10854
620     // The frame's last ref may be removed and it will be deleted by checkCompleted().
621     RefPtr<Frame> protector(m_frame);
622     
623     if (m_frame->document()->tokenizer())
624         m_frame->document()->tokenizer()->stopParsing();
625     m_frame->document()->finishParsing();
626
627     if (m_iconLoader)
628         m_iconLoader->stopLoading();
629 }
630
631 bool FrameLoader::closeURL()
632 {
633     saveDocumentState();
634     stopLoading(true);
635     m_frame->editor()->clearUndoRedoOperations();
636     return true;
637 }
638
639 void FrameLoader::cancelRedirection(bool cancelWithLoadInProgress)
640 {
641     m_cancellingWithLoadInProgress = cancelWithLoadInProgress;
642
643     stopRedirectionTimer();
644
645     m_scheduledRedirection.clear();
646 }
647
648 KURL FrameLoader::iconURL()
649 {
650     // If this isn't a top level frame, return nothing
651     if (m_frame->tree() && m_frame->tree()->parent())
652         return KURL();
653
654     // If we have an iconURL from a Link element, return that
655     if (!m_frame->document()->iconURL().isEmpty())
656         return KURL(m_frame->document()->iconURL());
657
658     // Don't return a favicon iconURL unless we're http or https
659     if (!m_URL.protocolIs("http") && !m_URL.protocolIs("https"))
660         return KURL();
661
662     KURL url;
663     url.setProtocol(m_URL.protocol());
664     url.setHost(m_URL.host());
665     if (int port = m_URL.port())
666         url.setPort(port);
667     url.setPath("/favicon.ico");
668     return url;
669 }
670
671 bool FrameLoader::didOpenURL(const KURL& url)
672 {
673     if (m_scheduledRedirection && m_scheduledRedirection->type == ScheduledRedirection::locationChangeDuringLoad)
674         // A redirect was scheduled before the document was created.
675         // This can happen when one frame changes another frame's location.
676         return false;
677
678     cancelRedirection();
679     m_frame->editor()->clearLastEditCommand();
680     closeURL();
681
682     m_isComplete = false;
683     m_isLoadingMainResource = true;
684     m_didCallImplicitClose = false;
685
686     m_frame->setJSStatusBarText(String());
687     m_frame->setJSDefaultStatusBarText(String());
688
689     m_URL = url;
690     if ((m_URL.protocolIs("http") || m_URL.protocolIs("https")) && !m_URL.host().isEmpty() && m_URL.path().isEmpty())
691         m_URL.setPath("/");
692     m_workingURL = m_URL;
693
694     started();
695
696     return true;
697 }
698
699 void FrameLoader::didExplicitOpen()
700 {
701     m_isComplete = false;
702     m_didCallImplicitClose = false;
703
704     // Calling document.open counts as committing the first real document load.
705     m_committedFirstRealDocumentLoad = true;
706     
707     // Prevent window.open(url) -- eg window.open("about:blank") -- from blowing away results
708     // from a subsequent window.document.open / window.document.write call. 
709     // Cancelling redirection here works for all cases because document.open 
710     // implicitly precedes document.write.
711     cancelRedirection(); 
712     if (m_frame->document()->url() != blankURL())
713         m_URL = m_frame->document()->url();
714 }
715
716 bool FrameLoader::executeIfJavaScriptURL(const KURL& url, bool userGesture, bool replaceDocument)
717 {
718     if (!url.protocolIs("javascript"))
719         return false;
720
721     if (m_frame->page() && !m_frame->page()->javaScriptURLsAreAllowed())
722         return true;
723
724     String script = decodeURLEscapeSequences(url.string().substring(strlen("javascript:")));
725     ScriptValue result = executeScript(script, userGesture);
726
727     String scriptResult;
728     if (!result.getString(scriptResult))
729         return true;
730
731     SecurityOrigin* currentSecurityOrigin = 0;
732     currentSecurityOrigin = m_frame->document()->securityOrigin();
733
734     // FIXME: We should always replace the document, but doing so
735     //        synchronously can cause crashes:
736     //        http://bugs.webkit.org/show_bug.cgi?id=16782
737     if (replaceDocument) {
738         begin(m_URL, true, currentSecurityOrigin);
739         write(scriptResult);
740         end();
741     }
742
743     return true;
744 }
745
746 ScriptValue FrameLoader::executeScript(const String& script, bool forceUserGesture)
747 {
748     return executeScript(ScriptSourceCode(script, forceUserGesture ? KURL() : m_URL));
749 }
750
751 ScriptValue FrameLoader::executeScript(const ScriptSourceCode& sourceCode)
752 {
753     if (!m_frame->script()->isEnabled() || m_frame->script()->isPaused())
754         return ScriptValue();
755
756     bool wasRunningScript = m_isRunningScript;
757     m_isRunningScript = true;
758
759     ScriptValue result = m_frame->script()->evaluate(sourceCode);
760
761     if (!wasRunningScript) {
762         m_isRunningScript = false;
763         submitFormAgain();
764         Document::updateDocumentsRendering();
765     }
766
767     return result;
768 }
769
770 void FrameLoader::cancelAndClear()
771 {
772     cancelRedirection();
773
774     if (!m_isComplete)
775         closeURL();
776
777     clear(false);
778     m_frame->script()->updatePlatformScriptObjects();
779 }
780
781 void FrameLoader::clear(bool clearWindowProperties, bool clearScriptObjects)
782 {
783     m_frame->editor()->clear();
784
785     if (!m_needsClear)
786         return;
787     m_needsClear = false;
788     
789     if (!m_frame->document()->inPageCache()) {
790         m_frame->document()->cancelParsing();
791         m_frame->document()->stopActiveDOMObjects();
792         if (m_frame->document()->attached()) {
793             m_frame->document()->willRemove();
794             m_frame->document()->detach();
795             
796             m_frame->document()->removeFocusedNodeOfSubtree(m_frame->document());
797         }
798     }
799
800     // Do this after detaching the document so that the unload event works.
801     if (clearWindowProperties) {
802         m_frame->clearDOMWindow();
803         m_frame->script()->clearWindowShell();
804     }
805
806     m_frame->selection()->clear();
807     m_frame->eventHandler()->clear();
808     if (m_frame->view())
809         m_frame->view()->clear();
810
811     m_frame->setSelectionGranularity(CharacterGranularity);
812
813     // Do not drop the document before the ScriptController and view are cleared
814     // as some destructors might still try to access the document.
815     m_frame->setDocument(0);
816     m_decoder = 0;
817
818     m_containsPlugIns = false;
819
820     if (clearScriptObjects)
821         m_frame->script()->clearScriptObjects();
822
823     m_redirectionTimer.stop();
824     m_scheduledRedirection.clear();
825
826     m_checkCompletedTimer.stop();
827     m_checkLoadCompleteTimer.stop();
828
829     m_receivedData = false;
830     m_isDisplayingInitialEmptyDocument = false;
831
832     if (!m_encodingWasChosenByUser)
833         m_encoding = String();
834 }
835
836 void FrameLoader::receivedFirstData()
837 {
838     begin(m_workingURL, false);
839
840     dispatchDidCommitLoad();
841     dispatchWindowObjectAvailable();
842     
843     String ptitle = m_documentLoader->title();
844     // If we have a title let the WebView know about it.
845     if (!ptitle.isNull())
846         m_client->dispatchDidReceiveTitle(ptitle);
847
848     m_workingURL = KURL();
849
850     double delay;
851     String url;
852     if (!m_documentLoader)
853         return;
854     if (!parseHTTPRefresh(m_documentLoader->response().httpHeaderField("Refresh"), false, delay, url))
855         return;
856
857     if (url.isEmpty())
858         url = m_URL.string();
859     else
860         url = m_frame->document()->completeURL(url).string();
861
862     scheduleHTTPRedirection(delay, url);
863 }
864
865 const String& FrameLoader::responseMIMEType() const
866 {
867     return m_responseMIMEType;
868 }
869
870 void FrameLoader::setResponseMIMEType(const String& type)
871 {
872     m_responseMIMEType = type;
873 }
874     
875 void FrameLoader::begin()
876 {
877     begin(KURL());
878 }
879
880 void FrameLoader::begin(const KURL& url, bool dispatch, SecurityOrigin* origin)
881 {
882     // We need to take a reference to the security origin because |clear|
883     // might destroy the document that owns it.
884     RefPtr<SecurityOrigin> forcedSecurityOrigin = origin;
885
886     RefPtr<Document> document;
887
888     // Create a new document before clearing the frame, because it may need to inherit an aliased security context.
889     if (!m_isDisplayingInitialEmptyDocument && m_client->shouldUsePluginDocument(m_responseMIMEType))
890         document = PluginDocument::create(m_frame);
891     else
892         document = DOMImplementation::createDocument(m_responseMIMEType, m_frame, m_frame->inViewSourceMode());
893
894     bool resetScripting = !(m_isDisplayingInitialEmptyDocument && m_frame->document()->securityOrigin()->isSecureTransitionTo(url));
895     clear(resetScripting, resetScripting);
896     if (resetScripting)
897         m_frame->script()->updatePlatformScriptObjects();
898
899     m_needsClear = true;
900     m_isComplete = false;
901     m_didCallImplicitClose = false;
902     m_isLoadingMainResource = true;
903     m_isDisplayingInitialEmptyDocument = m_creatingInitialEmptyDocument;
904
905     KURL ref(url);
906     ref.setUser(String());
907     ref.setPass(String());
908     ref.setRef(String());
909     m_outgoingReferrer = ref.string();
910     m_URL = url;
911
912     m_frame->setDocument(document);
913
914     if (dispatch)
915         dispatchWindowObjectAvailable();
916
917     document->setURL(m_URL);
918     if (m_decoder)
919         document->setDecoder(m_decoder.get());
920     if (forcedSecurityOrigin)
921         document->setSecurityOrigin(forcedSecurityOrigin.get());
922
923     m_frame->domWindow()->setURL(document->url());
924     m_frame->domWindow()->setSecurityOrigin(document->securityOrigin());
925
926     updatePolicyBaseURL();
927
928     Settings* settings = document->settings();
929     document->docLoader()->setAutoLoadImages(settings && settings->loadsImagesAutomatically());
930
931     if (m_documentLoader) {
932         String dnsPrefetchControl = m_documentLoader->response().httpHeaderField("X-DNS-Prefetch-Control");
933         if (!dnsPrefetchControl.isEmpty())
934             document->parseDNSPrefetchControlHeader(dnsPrefetchControl);
935     }
936
937 #if FRAME_LOADS_USER_STYLESHEET
938     KURL userStyleSheet = settings ? settings->userStyleSheetLocation() : KURL();
939     if (!userStyleSheet.isEmpty())
940         m_frame->setUserStyleSheetLocation(userStyleSheet);
941 #endif
942
943     restoreDocumentState();
944
945     document->implicitOpen();
946
947     if (m_frame->view())
948         m_frame->view()->setContentsSize(IntSize());
949 }
950
951 void FrameLoader::write(const char* str, int len, bool flush)
952 {
953     if (len == 0 && !flush)
954         return;
955     
956     if (len == -1)
957         len = strlen(str);
958
959     Tokenizer* tokenizer = m_frame->document()->tokenizer();
960     if (tokenizer && tokenizer->wantsRawData()) {
961         if (len > 0)
962             tokenizer->writeRawData(str, len);
963         return;
964     }
965     
966     if (!m_decoder) {
967         Settings* settings = m_frame->settings();
968         m_decoder = TextResourceDecoder::create(m_responseMIMEType, settings ? settings->defaultTextEncodingName() : String());
969         if (m_encoding.isEmpty()) {
970             Frame* parentFrame = m_frame->tree()->parent();
971             if (parentFrame && parentFrame->document()->securityOrigin()->canAccess(m_frame->document()->securityOrigin()))
972                 m_decoder->setEncoding(parentFrame->document()->inputEncoding(), TextResourceDecoder::DefaultEncoding);
973         } else {
974             m_decoder->setEncoding(m_encoding,
975                 m_encodingWasChosenByUser ? TextResourceDecoder::UserChosenEncoding : TextResourceDecoder::EncodingFromHTTPHeader);
976         }
977         m_frame->document()->setDecoder(m_decoder.get());
978     }
979
980     String decoded = m_decoder->decode(str, len);
981     if (flush)
982         decoded += m_decoder->flush();
983     if (decoded.isEmpty())
984         return;
985
986     if (!m_receivedData) {
987         m_receivedData = true;
988         if (m_decoder->encoding().usesVisualOrdering())
989             m_frame->document()->setVisuallyOrdered();
990         m_frame->document()->recalcStyle(Node::Force);
991     }
992
993     if (tokenizer) {
994         ASSERT(!tokenizer->wantsRawData());
995         tokenizer->write(decoded, true);
996     }
997 }
998
999 void FrameLoader::write(const String& str)
1000 {
1001     if (str.isNull())
1002         return;
1003
1004     if (!m_receivedData) {
1005         m_receivedData = true;
1006         m_frame->document()->setParseMode(Document::Strict);
1007     }
1008
1009     if (Tokenizer* tokenizer = m_frame->document()->tokenizer())
1010         tokenizer->write(str, true);
1011 }
1012
1013 void FrameLoader::end()
1014 {
1015     m_isLoadingMainResource = false;
1016     endIfNotLoadingMainResource();
1017 }
1018
1019 void FrameLoader::endIfNotLoadingMainResource()
1020 {
1021     if (m_isLoadingMainResource || !m_frame->page() || !m_frame->document())
1022         return;
1023
1024     // http://bugs.webkit.org/show_bug.cgi?id=10854
1025     // The frame's last ref may be removed and it can be deleted by checkCompleted(), 
1026     // so we'll add a protective refcount
1027     RefPtr<Frame> protector(m_frame);
1028
1029     // make sure nothing's left in there
1030     write(0, 0, true);
1031     m_frame->document()->finishParsing();
1032 }
1033
1034 void FrameLoader::iconLoadDecisionAvailable()
1035 {
1036     if (!m_mayLoadIconLater)
1037         return;
1038     LOG(IconDatabase, "FrameLoader %p was told a load decision is available for its icon", this);
1039     startIconLoader();
1040     m_mayLoadIconLater = false;
1041 }
1042
1043 void FrameLoader::startIconLoader()
1044 {
1045     // FIXME: We kick off the icon loader when the frame is done receiving its main resource.
1046     // But we should instead do it when we're done parsing the head element.
1047     if (!isLoadingMainFrame())
1048         return;
1049
1050     if (!iconDatabase() || !iconDatabase()->isEnabled())
1051         return;
1052     
1053     KURL url(iconURL());
1054     String urlString(url.string());
1055     if (urlString.isEmpty())
1056         return;
1057
1058     // If we're not reloading and the icon database doesn't say to load now then bail before we actually start the load
1059     if (loadType() != FrameLoadTypeReload && loadType() != FrameLoadTypeReloadFromOrigin) {
1060         IconLoadDecision decision = iconDatabase()->loadDecisionForIconURL(urlString, m_documentLoader.get());
1061         if (decision == IconLoadNo) {
1062             LOG(IconDatabase, "FrameLoader::startIconLoader() - Told not to load this icon, committing iconURL %s to database for pageURL mapping", urlString.ascii().data());
1063             commitIconURLToIconDatabase(url);
1064             
1065             // We were told not to load this icon - that means this icon is already known by the database
1066             // 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
1067             // has done it.  This is after registering for the notification so the WebView can call the appropriate delegate method.
1068             // Otherwise if the icon data *is* available, notify the delegate
1069             if (!iconDatabase()->iconDataKnownForIconURL(urlString)) {
1070                 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());
1071                 m_client->registerForIconNotification();
1072                 iconDatabase()->iconForPageURL(m_URL.string(), IntSize(0, 0));
1073                 iconDatabase()->iconForPageURL(originalRequestURL().string(), IntSize(0, 0));
1074             } else
1075                 m_client->dispatchDidReceiveIcon();
1076                 
1077             return;
1078         } 
1079         
1080         if (decision == IconLoadUnknown) {
1081             // In this case, we may end up loading the icon later, but we still want to commit the icon url mapping to the database
1082             // 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
1083             // We also tell the client to register for the notification that the icon is received now so it isn't missed in case the 
1084             // icon is later read in from disk
1085             LOG(IconDatabase, "FrameLoader %p might load icon %s later", this, urlString.ascii().data());
1086             m_mayLoadIconLater = true;    
1087             m_client->registerForIconNotification();
1088             commitIconURLToIconDatabase(url);
1089             return;
1090         }
1091     }
1092
1093     // This is either a reload or the icon database said "yes, load the icon", so kick off the load!
1094     if (!m_iconLoader)
1095         m_iconLoader.set(IconLoader::create(m_frame).release());
1096         
1097     m_iconLoader->startLoading();
1098 }
1099
1100 void FrameLoader::setLocalLoadPolicy(LocalLoadPolicy policy)
1101 {
1102     localLoadPolicy = policy;
1103 }
1104
1105 bool FrameLoader::restrictAccessToLocal()
1106 {
1107     return localLoadPolicy != FrameLoader::AllowLocalLoadsForAll;
1108 }
1109
1110 bool FrameLoader::allowSubstituteDataAccessToLocal()
1111 {
1112     return localLoadPolicy != FrameLoader::AllowLocalLoadsForLocalOnly;
1113 }
1114
1115 static LocalSchemesMap& localSchemes()
1116 {
1117     DEFINE_STATIC_LOCAL(LocalSchemesMap, localSchemes, ());
1118
1119     if (localSchemes.isEmpty()) {
1120         localSchemes.add("file");
1121 #if PLATFORM(MAC)
1122         localSchemes.add("applewebdata");
1123 #endif
1124 #if PLATFORM(QT)
1125         localSchemes.add("qrc");
1126 #endif
1127     }
1128
1129     return localSchemes;
1130 }
1131
1132 void FrameLoader::commitIconURLToIconDatabase(const KURL& icon)
1133 {
1134     ASSERT(iconDatabase());
1135     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());
1136     iconDatabase()->setIconURLForPageURL(icon.string(), m_URL.string());
1137     iconDatabase()->setIconURLForPageURL(icon.string(), originalRequestURL().string());
1138 }
1139
1140 void FrameLoader::restoreDocumentState()
1141 {
1142     Document* doc = m_frame->document();
1143         
1144     HistoryItem* itemToRestore = 0;
1145     
1146     switch (loadType()) {
1147         case FrameLoadTypeReload:
1148         case FrameLoadTypeReloadFromOrigin:
1149         case FrameLoadTypeSame:
1150         case FrameLoadTypeReplace:
1151             break;
1152         case FrameLoadTypeBack:
1153         case FrameLoadTypeForward:
1154         case FrameLoadTypeIndexedBackForward:
1155         case FrameLoadTypeRedirectWithLockedBackForwardList:
1156         case FrameLoadTypeStandard:
1157             itemToRestore = m_currentHistoryItem.get(); 
1158     }
1159     
1160     if (!itemToRestore)
1161         return;
1162
1163     LOG(Loading, "WebCoreLoading %s: restoring form state from %p", m_frame->tree()->name().string().utf8().data(), itemToRestore);
1164     doc->setStateForNewFormElements(itemToRestore->documentState());
1165 }
1166
1167 void FrameLoader::gotoAnchor()
1168 {
1169     // If our URL has no ref, then we have no place we need to jump to.
1170     // OTOH If CSS target was set previously, we want to set it to 0, recalc
1171     // and possibly repaint because :target pseudo class may have been
1172     // set (see bug 11321).
1173     if (!m_URL.hasRef() && !m_frame->document()->cssTarget())
1174         return;
1175
1176     String ref = m_URL.ref();
1177     if (gotoAnchor(ref))
1178         return;
1179
1180     // Try again after decoding the ref, based on the document's encoding.
1181     if (m_decoder)
1182         gotoAnchor(decodeURLEscapeSequences(ref, m_decoder->encoding()));
1183 }
1184
1185 void FrameLoader::finishedParsing()
1186 {
1187     if (m_creatingInitialEmptyDocument)
1188         return;
1189
1190     // This can be called from the Frame's destructor, in which case we shouldn't protect ourselves
1191     // because doing so will cause us to re-enter the destructor when protector goes out of scope.
1192     // Null-checking the FrameView indicates whether or not we're in the destructor.
1193     RefPtr<Frame> protector = m_frame->view() ? m_frame : 0;
1194
1195     m_client->dispatchDidFinishDocumentLoad();
1196
1197     checkCompleted();
1198
1199     if (!m_frame->view())
1200         return; // We are being destroyed by something checkCompleted called.
1201
1202     // Check if the scrollbars are really needed for the content.
1203     // If not, remove them, relayout, and repaint.
1204     m_frame->view()->restoreScrollbar();
1205
1206     gotoAnchor();
1207 }
1208
1209 void FrameLoader::loadDone()
1210 {
1211     checkCompleted();
1212 }
1213
1214 void FrameLoader::checkCompleted()
1215 {
1216     if (m_frame->view())
1217         m_frame->view()->checkStopDelayingDeferredRepaints();
1218
1219     // Any frame that hasn't completed yet?
1220     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
1221         if (!child->loader()->m_isComplete)
1222             return;
1223
1224     // Have we completed before?
1225     if (m_isComplete)
1226         return;
1227
1228     // Are we still parsing?
1229     if (m_frame->document()->parsing())
1230         return;
1231
1232     // Still waiting for images/scripts?
1233     if (numRequests(m_frame->document()))
1234         return;
1235
1236     // OK, completed.
1237     m_isComplete = true;
1238
1239     RefPtr<Frame> protect(m_frame);
1240     checkCallImplicitClose(); // if we didn't do it before
1241
1242     // Do not start a redirection timer for subframes here.
1243     // That is deferred until the parent is completed.
1244     if (m_scheduledRedirection && !m_frame->tree()->parent())
1245         startRedirectionTimer();
1246
1247     completed();
1248     if (m_frame->page())
1249         checkLoadComplete();
1250 }
1251
1252 void FrameLoader::checkCompletedTimerFired(Timer<FrameLoader>*)
1253 {
1254     checkCompleted();
1255 }
1256
1257 void FrameLoader::scheduleCheckCompleted()
1258 {
1259     if (!m_checkCompletedTimer.isActive())
1260         m_checkCompletedTimer.startOneShot(0);
1261 }
1262
1263 void FrameLoader::checkLoadCompleteTimerFired(Timer<FrameLoader>*)
1264 {
1265     if (!m_frame->page())
1266         return;
1267     checkLoadComplete();
1268 }
1269
1270 void FrameLoader::scheduleCheckLoadComplete()
1271 {
1272     if (!m_checkLoadCompleteTimer.isActive())
1273         m_checkLoadCompleteTimer.startOneShot(0);
1274 }
1275
1276 void FrameLoader::checkCallImplicitClose()
1277 {
1278     if (m_didCallImplicitClose || m_frame->document()->parsing())
1279         return;
1280
1281     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
1282         if (!child->loader()->m_isComplete) // still got a frame running -> too early
1283             return;
1284
1285     m_didCallImplicitClose = true;
1286     m_wasUnloadEventEmitted = false;
1287     m_frame->document()->implicitClose();
1288 }
1289
1290 KURL FrameLoader::baseURL() const
1291 {
1292     ASSERT(m_frame->document());
1293     return m_frame->document()->baseURL();
1294 }
1295
1296 String FrameLoader::baseTarget() const
1297 {
1298     ASSERT(m_frame->document());
1299     return m_frame->document()->baseTarget();
1300 }
1301
1302 KURL FrameLoader::completeURL(const String& url)
1303 {
1304     ASSERT(m_frame->document());
1305     return m_frame->document()->completeURL(url);
1306 }
1307
1308 void FrameLoader::scheduleHTTPRedirection(double delay, const String& url)
1309 {
1310     if (delay < 0 || delay > INT_MAX / 1000)
1311         return;
1312         
1313     if (!m_frame->page())
1314         return;
1315
1316     // We want a new history item if the refresh timeout is > 1 second.
1317     if (!m_scheduledRedirection || delay <= m_scheduledRedirection->delay)
1318         scheduleRedirection(new ScheduledRedirection(delay, url, true, delay <= 1, false, false));
1319 }
1320
1321 void FrameLoader::scheduleLocationChange(const String& url, const String& referrer, bool lockHistory, bool lockBackForwardList, bool wasUserGesture)
1322 {
1323     if (!m_frame->page())
1324         return;
1325
1326     // If the URL we're going to navigate to is the same as the current one, except for the
1327     // fragment part, we don't need to schedule the location change.
1328     KURL parsedURL(url);
1329     if (parsedURL.hasRef() && equalIgnoringRef(m_URL, parsedURL)) {
1330         changeLocation(url, referrer, lockHistory, lockBackForwardList, wasUserGesture);
1331         return;
1332     }
1333
1334     // Handle a location change of a page with no document as a special case.
1335     // This may happen when a frame changes the location of another frame.
1336     bool duringLoad = !m_committedFirstRealDocumentLoad;
1337
1338     // If a redirect was scheduled during a load, then stop the current load.
1339     // Otherwise when the current load transitions from a provisional to a 
1340     // committed state, pending redirects may be cancelled. 
1341     if (duringLoad) {
1342         if (m_provisionalDocumentLoader)
1343             m_provisionalDocumentLoader->stopLoading();
1344         stopLoading(true);   
1345     }
1346
1347     ScheduledRedirection::Type type = duringLoad
1348         ? ScheduledRedirection::locationChangeDuringLoad : ScheduledRedirection::locationChange;
1349     scheduleRedirection(new ScheduledRedirection(type, url, referrer, lockHistory, lockBackForwardList, wasUserGesture, false));
1350 }
1351
1352 void FrameLoader::scheduleRefresh(bool wasUserGesture)
1353 {
1354     if (!m_frame->page())
1355         return;
1356
1357     ScheduledRedirection::Type type = ScheduledRedirection::locationChange;
1358     scheduleRedirection(new ScheduledRedirection(type, m_URL.string(), m_outgoingReferrer, true, true, wasUserGesture, true));
1359 }
1360
1361 bool FrameLoader::isLocationChange(const ScheduledRedirection& redirection)
1362 {
1363     switch (redirection.type) {
1364         case ScheduledRedirection::redirection:
1365             return false;
1366         case ScheduledRedirection::historyNavigation:
1367         case ScheduledRedirection::locationChange:
1368         case ScheduledRedirection::locationChangeDuringLoad:
1369             return true;
1370     }
1371     ASSERT_NOT_REACHED();
1372     return false;
1373 }
1374
1375 void FrameLoader::scheduleHistoryNavigation(int steps)
1376 {
1377     if (!m_frame->page())
1378         return;
1379
1380     // navigation will always be allowed in the 0 steps case, which is OK because that's supposed to force a reload.
1381     if (!canGoBackOrForward(steps)) {
1382         cancelRedirection();
1383         return;
1384     }
1385
1386     // If the steps to navigate is not zero (which needs to force a reload), and if we think the navigation is going to be a fragment load
1387     // (when the URL we're going to navigate to is the same as the current one, except for the fragment part - but not exactly the same because that's a reload),
1388     // then we don't need to schedule the navigation.
1389     if (steps != 0) {
1390         KURL destination = historyURL(steps);
1391         // FIXME: This doesn't seem like a reliable way to tell whether or not the load will be a fragment load.
1392         if (equalIgnoringRef(m_URL, destination) && m_URL != destination) {
1393             goBackOrForward(steps);
1394             return;
1395         }
1396     }
1397     
1398     scheduleRedirection(new ScheduledRedirection(steps));
1399 }
1400
1401 void FrameLoader::goBackOrForward(int distance)
1402 {
1403     if (distance == 0)
1404         return;
1405         
1406     Page* page = m_frame->page();
1407     if (!page)
1408         return;
1409     BackForwardList* list = page->backForwardList();
1410     if (!list)
1411         return;
1412     
1413     HistoryItem* item = list->itemAtIndex(distance);
1414     if (!item) {
1415         if (distance > 0) {
1416             int forwardListCount = list->forwardListCount();
1417             if (forwardListCount > 0) 
1418                 item = list->itemAtIndex(forwardListCount);
1419         } else {
1420             int backListCount = list->backListCount();
1421             if (backListCount > 0)
1422                 item = list->itemAtIndex(-backListCount);
1423         }
1424     }
1425     
1426     ASSERT(item); // we should not reach this line with an empty back/forward list
1427     if (item)
1428         page->goToItem(item, FrameLoadTypeIndexedBackForward);
1429 }
1430
1431 void FrameLoader::redirectionTimerFired(Timer<FrameLoader>*)
1432 {
1433     ASSERT(m_frame->page());
1434
1435     OwnPtr<ScheduledRedirection> redirection(m_scheduledRedirection.release());
1436
1437     switch (redirection->type) {
1438         case ScheduledRedirection::redirection:
1439         case ScheduledRedirection::locationChange:
1440         case ScheduledRedirection::locationChangeDuringLoad:
1441             changeLocation(redirection->url, redirection->referrer,
1442                 redirection->lockHistory, redirection->lockBackForwardList, redirection->wasUserGesture, redirection->wasRefresh);
1443             return;
1444         case ScheduledRedirection::historyNavigation:
1445             if (redirection->historySteps == 0) {
1446                 // Special case for go(0) from a frame -> reload only the frame
1447                 urlSelected(m_URL, "", 0, redirection->lockHistory, redirection->lockBackForwardList, redirection->wasUserGesture);
1448                 return;
1449             }
1450             // go(i!=0) from a frame navigates into the history of the frame only,
1451             // in both IE and NS (but not in Mozilla). We can't easily do that.
1452             goBackOrForward(redirection->historySteps);
1453             return;
1454     }
1455
1456     ASSERT_NOT_REACHED();
1457 }
1458
1459 /*
1460     In the case of saving state about a page with frames, we store a tree of items that mirrors the frame tree.  
1461     The item that was the target of the user's navigation is designated as the "targetItem".  
1462     When this method is called with doClip=YES we're able to create the whole tree except for the target's children, 
1463     which will be loaded in the future.  That part of the tree will be filled out as the child loads are committed.
1464 */
1465 void FrameLoader::loadURLIntoChildFrame(const KURL& url, const String& referer, Frame* childFrame)
1466 {
1467     ASSERT(childFrame);
1468     HistoryItem* parentItem = currentHistoryItem();
1469     FrameLoadType loadType = this->loadType();
1470     FrameLoadType childLoadType = FrameLoadTypeRedirectWithLockedBackForwardList;
1471
1472     KURL workingURL = url;
1473     
1474     // If we're moving in the backforward list, we might want to replace the content
1475     // of this child frame with whatever was there at that point.
1476     if (parentItem && parentItem->children().size() && isBackForwardLoadType(loadType)) {
1477         HistoryItem* childItem = parentItem->childItemWithName(childFrame->tree()->name());
1478         if (childItem) {
1479             // Use the original URL to ensure we get all the side-effects, such as
1480             // onLoad handlers, of any redirects that happened. An example of where
1481             // this is needed is Radar 3213556.
1482             workingURL = KURL(childItem->originalURLString());
1483             childLoadType = loadType;
1484             childFrame->loader()->setProvisionalHistoryItem(childItem);
1485         }
1486     }
1487
1488     RefPtr<Archive> subframeArchive = activeDocumentLoader()->popArchiveForSubframe(childFrame->tree()->name());
1489     
1490     if (subframeArchive)
1491         childFrame->loader()->loadArchive(subframeArchive.release());
1492     else
1493         childFrame->loader()->loadURL(workingURL, referer, String(), false, childLoadType, 0, 0);
1494 }
1495
1496 void FrameLoader::loadArchive(PassRefPtr<Archive> prpArchive)
1497 {
1498     RefPtr<Archive> archive = prpArchive;
1499     
1500     ArchiveResource* mainResource = archive->mainResource();
1501     ASSERT(mainResource);
1502     if (!mainResource)
1503         return;
1504         
1505     SubstituteData substituteData(mainResource->data(), mainResource->mimeType(), mainResource->textEncoding(), KURL());
1506     
1507     ResourceRequest request(mainResource->url());
1508 #if PLATFORM(MAC)
1509     request.applyWebArchiveHackForMail();
1510 #endif
1511
1512     RefPtr<DocumentLoader> documentLoader = m_client->createDocumentLoader(request, substituteData);
1513     documentLoader->addAllArchiveResources(archive.get());
1514     load(documentLoader.get());
1515 }
1516
1517 String FrameLoader::encoding() const
1518 {
1519     if (m_encodingWasChosenByUser && !m_encoding.isEmpty())
1520         return m_encoding;
1521     if (m_decoder && m_decoder->encoding().isValid())
1522         return m_decoder->encoding().name();
1523     Settings* settings = m_frame->settings();
1524     return settings ? settings->defaultTextEncodingName() : String();
1525 }
1526
1527 bool FrameLoader::gotoAnchor(const String& name)
1528 {
1529     ASSERT(m_frame->document());
1530
1531     if (!m_frame->document()->haveStylesheetsLoaded()) {
1532         m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(true);
1533         return false;
1534     }
1535
1536     m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(false);
1537
1538     Element* anchorNode = m_frame->document()->findAnchor(name);
1539
1540 #if ENABLE(SVG)
1541     if (m_frame->document()->isSVGDocument()) {
1542         if (name.startsWith("xpointer(")) {
1543             // We need to parse the xpointer reference here
1544         } else if (name.startsWith("svgView(")) {
1545             RefPtr<SVGSVGElement> svg = static_cast<SVGDocument*>(m_frame->document())->rootElement();
1546             if (!svg->currentView()->parseViewSpec(name))
1547                 return false;
1548             svg->setUseCurrentView(true);
1549         } else {
1550             if (anchorNode && anchorNode->hasTagName(SVGNames::viewTag)) {
1551                 RefPtr<SVGViewElement> viewElement = anchorNode->hasTagName(SVGNames::viewTag) ? static_cast<SVGViewElement*>(anchorNode) : 0;
1552                 if (viewElement.get()) {
1553                     RefPtr<SVGSVGElement> svg = static_cast<SVGSVGElement*>(SVGLocatable::nearestViewportElement(viewElement.get()));
1554                     svg->inheritViewAttributes(viewElement.get());
1555                 }
1556             }
1557         }
1558         // FIXME: need to decide which <svg> to focus on, and zoom to that one
1559         // FIXME: need to actually "highlight" the viewTarget(s)
1560     }
1561 #endif
1562
1563     m_frame->document()->setCSSTarget(anchorNode); // Setting to null will clear the current target.
1564   
1565     // Implement the rule that "" and "top" both mean top of page as in other browsers.
1566     if (!anchorNode && !(name.isEmpty() || equalIgnoringCase(name, "top")))
1567         return false;
1568
1569     // We need to update the layout before scrolling, otherwise we could
1570     // really mess things up if an anchor scroll comes at a bad moment.
1571     m_frame->document()->updateRendering();
1572     // Only do a layout if changes have occurred that make it necessary.
1573     if (m_frame->view() && m_frame->contentRenderer() && m_frame->contentRenderer()->needsLayout())
1574         m_frame->view()->layout();
1575   
1576     // Scroll nested layers and frames to reveal the anchor.
1577     // Align to the top and to the closest side (this matches other browsers).
1578     RenderObject* renderer;
1579     IntRect rect;
1580     if (!anchorNode)
1581         renderer = m_frame->document()->renderer(); // top of document
1582     else {
1583         renderer = anchorNode->renderer();
1584         rect = anchorNode->getRect();
1585     }
1586     if (renderer)
1587         renderer->enclosingLayer()->scrollRectToVisible(rect, true, RenderLayer::gAlignToEdgeIfNeeded, RenderLayer::gAlignTopAlways);
1588
1589     return true;
1590 }
1591
1592 bool FrameLoader::requestObject(RenderPart* renderer, const String& url, const AtomicString& frameName,
1593     const String& mimeType, const Vector<String>& paramNames, const Vector<String>& paramValues)
1594 {
1595     if (url.isEmpty() && mimeType.isEmpty())
1596         return false;
1597
1598     KURL completedURL;
1599     if (!url.isEmpty())
1600         completedURL = completeURL(url);
1601
1602     bool useFallback;
1603     if (shouldUsePlugin(completedURL, mimeType, renderer->hasFallbackContent(), useFallback)) {
1604         Settings* settings = m_frame->settings();
1605         if (!settings || !settings->arePluginsEnabled() || 
1606             (!settings->isJavaEnabled() && MIMETypeRegistry::isJavaAppletMIMEType(mimeType)))
1607             return false;
1608         return loadPlugin(renderer, completedURL, mimeType, paramNames, paramValues, useFallback);
1609     }
1610
1611     ASSERT(renderer->node()->hasTagName(objectTag) || renderer->node()->hasTagName(embedTag));
1612     HTMLPlugInElement* element = static_cast<HTMLPlugInElement*>(renderer->node());
1613     
1614     // FIXME: OK to always make a new frame? When does the old frame get removed?
1615     return loadSubframe(element, completedURL, frameName, m_outgoingReferrer);
1616 }
1617
1618 bool FrameLoader::shouldUsePlugin(const KURL& url, const String& mimeType, bool hasFallback, bool& useFallback)
1619 {
1620     if (m_client->shouldUsePluginDocument(mimeType)) {
1621         useFallback = false;
1622         return true;
1623     }
1624
1625     // Allow other plug-ins to win over QuickTime because if the user has installed a plug-in that
1626     // can handle TIFF (which QuickTime can also handle) they probably intended to override QT.
1627     if (m_frame->page() && (mimeType == "image/tiff" || mimeType == "image/tif" || mimeType == "image/x-tiff")) {
1628         const PluginData* pluginData = m_frame->page()->pluginData();
1629         String pluginName = pluginData ? pluginData->pluginNameForMimeType(mimeType) : String();
1630         if (!pluginName.isEmpty() && !pluginName.contains("QuickTime", false)) 
1631             return true;
1632     }
1633         
1634     ObjectContentType objectType = m_client->objectContentType(url, mimeType);
1635     // If an object's content can't be handled and it has no fallback, let
1636     // it be handled as a plugin to show the broken plugin icon.
1637     useFallback = objectType == ObjectContentNone && hasFallback;
1638     return objectType == ObjectContentNone || objectType == ObjectContentNetscapePlugin || objectType == ObjectContentOtherPlugin;
1639 }
1640
1641 static HTMLPlugInElement* toPlugInElement(Node* node)
1642 {
1643     if (!node)
1644         return 0;
1645
1646 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
1647     ASSERT(node->hasTagName(objectTag) || node->hasTagName(embedTag) 
1648         || node->hasTagName(videoTag) || node->hasTagName(audioTag)
1649         || node->hasTagName(appletTag));
1650 #else
1651     ASSERT(node->hasTagName(objectTag) || node->hasTagName(embedTag) 
1652         || node->hasTagName(appletTag));
1653 #endif
1654
1655     return static_cast<HTMLPlugInElement*>(node);
1656 }
1657     
1658 bool FrameLoader::loadPlugin(RenderPart* renderer, const KURL& url, const String& mimeType, 
1659     const Vector<String>& paramNames, const Vector<String>& paramValues, bool useFallback)
1660 {
1661     Widget* widget = 0;
1662
1663     if (renderer && !useFallback) {
1664         HTMLPlugInElement* element = toPlugInElement(renderer->node());
1665
1666         if (!canLoad(url, String(), frame()->document())) {
1667             FrameLoader::reportLocalLoadFailed(m_frame, url.string());
1668             return false;
1669         }
1670
1671         widget = m_client->createPlugin(IntSize(renderer->contentWidth(), renderer->contentHeight()), 
1672                                         element, url, paramNames, paramValues, mimeType,
1673                                         m_frame->document()->isPluginDocument());
1674         if (widget) {
1675             renderer->setWidget(widget);
1676             m_containsPlugIns = true;
1677         }
1678     }
1679
1680     return widget != 0;
1681 }
1682
1683 void FrameLoader::clearRecordedFormValues()
1684 {
1685     m_formAboutToBeSubmitted = 0;
1686     m_formValuesAboutToBeSubmitted.clear();
1687 }
1688
1689 void FrameLoader::setFormAboutToBeSubmitted(PassRefPtr<HTMLFormElement> element)
1690 {
1691     m_formAboutToBeSubmitted = element;
1692 }
1693
1694 void FrameLoader::recordFormValue(const String& name, const String& value)
1695 {
1696     m_formValuesAboutToBeSubmitted.set(name, value);
1697 }
1698
1699 void FrameLoader::parentCompleted()
1700 {
1701     if (m_scheduledRedirection && !m_redirectionTimer.isActive())
1702         startRedirectionTimer();
1703 }
1704
1705 String FrameLoader::outgoingReferrer() const
1706 {
1707     return m_outgoingReferrer;
1708 }
1709
1710 String FrameLoader::outgoingOrigin() const
1711 {
1712     return m_frame->document()->securityOrigin()->toString();
1713 }
1714
1715 Frame* FrameLoader::opener()
1716 {
1717     return m_opener;
1718 }
1719
1720 void FrameLoader::setOpener(Frame* opener)
1721 {
1722     if (m_opener)
1723         m_opener->loader()->m_openedFrames.remove(m_frame);
1724     if (opener)
1725         opener->loader()->m_openedFrames.add(m_frame);
1726     m_opener = opener;
1727
1728     if (m_frame->document()) {
1729         m_frame->document()->initSecurityContext();
1730         m_frame->domWindow()->setSecurityOrigin(m_frame->document()->securityOrigin());
1731     }
1732 }
1733
1734 bool FrameLoader::openedByDOM() const
1735 {
1736     return m_openedByDOM;
1737 }
1738
1739 void FrameLoader::setOpenedByDOM()
1740 {
1741     m_openedByDOM = true;
1742 }
1743
1744 void FrameLoader::handleFallbackContent()
1745 {
1746     HTMLFrameOwnerElement* owner = m_frame->ownerElement();
1747     if (!owner || !owner->hasTagName(objectTag))
1748         return;
1749     static_cast<HTMLObjectElement*>(owner)->renderFallbackContent();
1750 }
1751
1752 void FrameLoader::provisionalLoadStarted()
1753 {
1754     Page* page = m_frame->page();
1755     
1756     // this is used to update the current history item
1757     // in the event of a navigation aytime during loading
1758     m_navigationDuringLoad = false;
1759     if (page) {
1760         Document *document = page->mainFrame()->document();
1761         m_navigationDuringLoad = !page->mainFrame()->loader()->isComplete() || (document && document->processingLoadEvent());
1762     }
1763     
1764     m_firstLayoutDone = false;
1765     cancelRedirection(true);
1766     m_client->provisionalLoadStarted();
1767 }
1768
1769 bool FrameLoader::userGestureHint()
1770 {
1771     Frame* frame = m_frame->tree()->top();
1772     if (!frame->script()->isEnabled())
1773         return true; // If JavaScript is disabled, a user gesture must have initiated the navigation.
1774     return frame->script()->processingUserGesture(); // FIXME: Use pageIsProcessingUserGesture.
1775 }
1776
1777 void FrameLoader::didNotOpenURL(const KURL& url)
1778 {
1779     if (m_submittedFormURL == url)
1780         m_submittedFormURL = KURL();
1781 }
1782
1783 void FrameLoader::resetMultipleFormSubmissionProtection()
1784 {
1785     m_submittedFormURL = KURL();
1786 }
1787
1788 void FrameLoader::setEncoding(const String& name, bool userChosen)
1789 {
1790     if (!m_workingURL.isEmpty())
1791         receivedFirstData();
1792     m_encoding = name;
1793     m_encodingWasChosenByUser = userChosen;
1794 }
1795
1796 void FrameLoader::addData(const char* bytes, int length)
1797 {
1798     ASSERT(m_workingURL.isEmpty());
1799     ASSERT(m_frame->document());
1800     ASSERT(m_frame->document()->parsing());
1801     write(bytes, length);
1802 }
1803
1804 bool FrameLoader::canCachePageContainingThisFrame()
1805 {
1806     return m_documentLoader
1807         && m_documentLoader->mainDocumentError().isNull()
1808         && !m_frame->tree()->childCount()
1809         // FIXME: If we ever change this so that frames with plug-ins will be cached,
1810         // we need to make sure that we don't cache frames that have outstanding NPObjects
1811         // (objects created by the plug-in). Since there is no way to pause/resume a Netscape plug-in,
1812         // they would need to be destroyed and then recreated, and there is no way that we can recreate
1813         // the right NPObjects. See <rdar://problem/5197041> for more information.
1814         && !m_containsPlugIns
1815         && !m_URL.protocolIs("https")
1816         && !m_frame->document()->hasWindowEventListener(eventNames().unloadEvent)
1817 #if ENABLE(DATABASE)
1818         && !m_frame->document()->hasOpenDatabases()
1819 #endif
1820         && !m_frame->document()->usingGeolocation()
1821         && m_currentHistoryItem
1822         && !isQuickRedirectComing()
1823         && !m_documentLoader->isLoadingInAPISense()
1824         && !m_documentLoader->isStopping()
1825         && m_frame->document()->canSuspendActiveDOMObjects()
1826 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
1827         // FIXME: We should investigating caching frames that have an associated
1828         // application cache. <rdar://problem/5917899> tracks that work.
1829         && !m_documentLoader->applicationCache()
1830         && !m_documentLoader->candidateApplicationCacheGroup()
1831 #endif
1832         && m_client->canCachePage()
1833         ;
1834 }
1835
1836 bool FrameLoader::canCachePage()
1837 {
1838 #ifndef NDEBUG
1839     logCanCachePageDecision();
1840 #endif
1841     
1842     // Cache the page, if possible.
1843     // Don't write to the cache if in the middle of a redirect, since we will want to
1844     // store the final page we end up on.
1845     // No point writing to the cache on a reload or loadSame, since we will just write
1846     // over it again when we leave that page.
1847     // FIXME: <rdar://problem/4886592> - We should work out the complexities of caching pages with frames as they
1848     // are the most interesting pages on the web, and often those that would benefit the most from caching!
1849     FrameLoadType loadType = this->loadType();
1850     
1851     return !m_frame->tree()->parent()
1852         && canCachePageContainingThisFrame()
1853         && m_frame->page()
1854         && m_frame->page()->backForwardList()->enabled()
1855         && m_frame->page()->backForwardList()->capacity() > 0
1856         && m_frame->page()->settings()->usesPageCache()
1857         && loadType != FrameLoadTypeReload 
1858         && loadType != FrameLoadTypeReloadFromOrigin
1859         && loadType != FrameLoadTypeSame
1860         ;
1861 }
1862
1863 #ifndef NDEBUG
1864 static String& pageCacheLogPrefix(int indentLevel)
1865 {
1866     static int previousIndent = -1;
1867     DEFINE_STATIC_LOCAL(String, prefix, ());
1868     
1869     if (indentLevel != previousIndent) {    
1870         previousIndent = indentLevel;
1871         prefix.truncate(0);
1872         for (int i = 0; i < previousIndent; ++i)
1873             prefix += "    ";
1874     }
1875     
1876     return prefix;
1877 }
1878
1879 static void pageCacheLog(const String& prefix, const String& message)
1880 {
1881     LOG(PageCache, "%s%s", prefix.utf8().data(), message.utf8().data());
1882 }
1883
1884 #define PCLOG(...) pageCacheLog(pageCacheLogPrefix(indentLevel), String::format(__VA_ARGS__))
1885
1886 void FrameLoader::logCanCachePageDecision()
1887 {
1888     // Only bother logging for main frames that have actually loaded and have content.
1889     if (m_creatingInitialEmptyDocument)
1890         return;
1891     KURL currentURL = m_documentLoader ? m_documentLoader->url() : KURL();
1892     if (currentURL.isEmpty())
1893         return;
1894
1895     int indentLevel = 0;
1896     PCLOG("--------\n Determining if page can be cached:");
1897
1898     bool cannotCache = !logCanCacheFrameDecision(1);
1899         
1900     FrameLoadType loadType = this->loadType();
1901     do {
1902         if (m_frame->tree()->parent())
1903             { PCLOG("   -Frame has a parent frame"); cannotCache = true; }
1904         if (!m_frame->page()) {
1905             PCLOG("   -There is no Page object");
1906             cannotCache = true;
1907             break;
1908         }
1909         if (!m_frame->page()->backForwardList()->enabled())
1910             { PCLOG("   -The back/forward list is disabled"); cannotCache = true; }
1911         if (!(m_frame->page()->backForwardList()->capacity() > 0))
1912             { PCLOG("   -The back/forward list has a 0 capacity"); cannotCache = true; }
1913         if (!m_frame->page()->settings()->usesPageCache())
1914             { PCLOG("   -Page settings says b/f cache disabled"); cannotCache = true; }
1915         if (loadType == FrameLoadTypeReload)
1916             { PCLOG("   -Load type is: Reload"); cannotCache = true; }
1917         if (loadType == FrameLoadTypeReloadFromOrigin)
1918             { PCLOG("   -Load type is: Reload from origin"); cannotCache = true; }
1919         if (loadType == FrameLoadTypeSame)
1920             { PCLOG("   -Load type is: Same"); cannotCache = true; }
1921     } while (false);
1922     
1923     PCLOG(cannotCache ? " Page CANNOT be cached\n--------" : " Page CAN be cached\n--------");
1924 }
1925
1926 bool FrameLoader::logCanCacheFrameDecision(int indentLevel)
1927 {
1928     // Only bother logging for frames that have actually loaded and have content.
1929     if (m_creatingInitialEmptyDocument)
1930         return false;
1931     KURL currentURL = m_documentLoader ? m_documentLoader->url() : KURL();
1932     if (currentURL.isEmpty())
1933         return false;
1934
1935     PCLOG("+---");
1936     KURL newURL = m_provisionalDocumentLoader ? m_provisionalDocumentLoader->url() : KURL();
1937     if (!newURL.isEmpty())
1938         PCLOG(" Determining if frame can be cached navigating from (%s) to (%s):", currentURL.string().utf8().data(), newURL.string().utf8().data());
1939     else
1940         PCLOG(" Determining if subframe with URL (%s) can be cached:", currentURL.string().utf8().data());
1941         
1942     bool cannotCache = false;
1943
1944     do {
1945         if (!m_documentLoader) {
1946             PCLOG("   -There is no DocumentLoader object");
1947             cannotCache = true;
1948             break;
1949         }
1950         if (!m_documentLoader->mainDocumentError().isNull())
1951             { PCLOG("   -Main document has an error"); cannotCache = true; }
1952         if (m_frame->tree()->childCount())
1953             { PCLOG("   -Frame has child frames"); cannotCache = true; }
1954         if (m_containsPlugIns)
1955             { PCLOG("   -Frame contains plugins"); cannotCache = true; }
1956         if (m_URL.protocolIs("https"))
1957             { PCLOG("   -Frame is HTTPS"); cannotCache = true; }
1958         if (m_frame->document()->hasWindowEventListener(eventNames().unloadEvent))
1959             { PCLOG("   -Frame has an unload event listener"); cannotCache = true; }
1960 #if ENABLE(DATABASE)
1961         if (m_frame->document()->hasOpenDatabases())
1962             { PCLOG("   -Frame has open database handles"); cannotCache = true; }
1963 #endif
1964         if (m_frame->document()->usingGeolocation())
1965             { PCLOG("   -Frame uses Geolocation"); cannotCache = true; }
1966         if (!m_currentHistoryItem)
1967             { PCLOG("   -No current history item"); cannotCache = true; }
1968         if (isQuickRedirectComing())
1969             { PCLOG("   -Quick redirect is coming"); cannotCache = true; }
1970         if (m_documentLoader->isLoadingInAPISense())
1971             { PCLOG("   -DocumentLoader is still loading in API sense"); cannotCache = true; }
1972         if (m_documentLoader->isStopping())
1973             { PCLOG("   -DocumentLoader is in the middle of stopping"); cannotCache = true; }
1974         if (!m_frame->document()->canSuspendActiveDOMObjects())
1975             { PCLOG("   -The document cannot suspect its active DOM Objects"); cannotCache = true; }
1976 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
1977         if (m_documentLoader->applicationCache())
1978             { PCLOG("   -The DocumentLoader has an active application cache"); cannotCache = true; }
1979         if (m_documentLoader->candidateApplicationCacheGroup())
1980             { PCLOG("   -The DocumentLoader has a candidateApplicationCacheGroup"); cannotCache = true; }
1981 #endif
1982         if (!m_client->canCachePage())
1983             { PCLOG("   -The client says this frame cannot be cached"); cannotCache = true; }
1984     } while (false);
1985
1986     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
1987         if (!child->loader()->logCanCacheFrameDecision(indentLevel + 1))
1988             cannotCache = true;
1989     
1990     PCLOG(cannotCache ? " Frame CANNOT be cached" : " Frame CAN be cached");
1991     PCLOG("+---");
1992
1993     return !cannotCache;
1994 }
1995 #endif
1996
1997 void FrameLoader::updatePolicyBaseURL()
1998 {
1999     if (m_frame->tree()->parent())
2000         setPolicyBaseURL(m_frame->tree()->parent()->document()->policyBaseURL());
2001     else
2002         setPolicyBaseURL(m_URL);
2003 }
2004
2005 void FrameLoader::setPolicyBaseURL(const KURL& url)
2006 {
2007     m_frame->document()->setPolicyBaseURL(url);
2008     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
2009         child->loader()->setPolicyBaseURL(url);
2010 }
2011
2012 // This does the same kind of work that didOpenURL does, except it relies on the fact
2013 // that a higher level already checked that the URLs match and the scrolling is the right thing to do.
2014 void FrameLoader::scrollToAnchor(const KURL& url)
2015 {
2016     m_URL = url;
2017     updateHistoryForAnchorScroll();
2018
2019     // If we were in the autoscroll/panScroll mode we want to stop it before following the link to the anchor
2020     m_frame->eventHandler()->stopAutoscrollTimer();
2021     started();
2022     gotoAnchor();
2023
2024     // It's important to model this as a load that starts and immediately finishes.
2025     // Otherwise, the parent frame may think we never finished loading.
2026     m_isComplete = false;
2027     checkCompleted();
2028 }
2029
2030 bool FrameLoader::isComplete() const
2031 {
2032     return m_isComplete;
2033 }
2034
2035 void FrameLoader::scheduleRedirection(ScheduledRedirection* redirection)
2036 {
2037     ASSERT(m_frame->page());
2038
2039     stopRedirectionTimer();
2040     m_scheduledRedirection.set(redirection);
2041     if (!m_isComplete && redirection->type != ScheduledRedirection::redirection)
2042         completed();
2043     if (m_isComplete || redirection->type != ScheduledRedirection::redirection)
2044         startRedirectionTimer();
2045 }
2046
2047 void FrameLoader::startRedirectionTimer()
2048 {
2049     ASSERT(m_frame->page());
2050     ASSERT(m_scheduledRedirection);
2051
2052     m_redirectionTimer.stop();
2053     m_redirectionTimer.startOneShot(m_scheduledRedirection->delay);
2054
2055     switch (m_scheduledRedirection->type) {
2056         case ScheduledRedirection::redirection:
2057         case ScheduledRedirection::locationChange:
2058         case ScheduledRedirection::locationChangeDuringLoad:
2059             clientRedirected(KURL(m_scheduledRedirection->url),
2060                 m_scheduledRedirection->delay,
2061                 currentTime() + m_redirectionTimer.nextFireInterval(),
2062                 m_scheduledRedirection->lockBackForwardList,
2063                 m_isExecutingJavaScriptFormAction);
2064             return;
2065         case ScheduledRedirection::historyNavigation:
2066             // Don't report history navigations.
2067             return;
2068     }
2069     ASSERT_NOT_REACHED();
2070 }
2071
2072 void FrameLoader::stopRedirectionTimer()
2073 {
2074     if (!m_redirectionTimer.isActive())
2075         return;
2076
2077     m_redirectionTimer.stop();
2078
2079     if (m_scheduledRedirection) {
2080         switch (m_scheduledRedirection->type) {
2081             case ScheduledRedirection::redirection:
2082             case ScheduledRedirection::locationChange:
2083             case ScheduledRedirection::locationChangeDuringLoad:
2084                 clientRedirectCancelledOrFinished(m_cancellingWithLoadInProgress);
2085                 return;
2086             case ScheduledRedirection::historyNavigation:
2087                 // Don't report history navigations.
2088                 return;
2089         }
2090         ASSERT_NOT_REACHED();
2091     }
2092 }
2093
2094 void FrameLoader::completed()
2095 {
2096     RefPtr<Frame> protect(m_frame);
2097     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
2098         child->loader()->parentCompleted();
2099     if (Frame* parent = m_frame->tree()->parent())
2100         parent->loader()->checkCompleted();
2101     submitFormAgain();
2102 }
2103
2104 void FrameLoader::started()
2105 {
2106     for (Frame* frame = m_frame; frame; frame = frame->tree()->parent())
2107         frame->loader()->m_isComplete = false;
2108 }
2109
2110 bool FrameLoader::containsPlugins() const 
2111
2112     return m_containsPlugIns;
2113 }
2114
2115 void FrameLoader::prepareForLoadStart()
2116 {
2117     if (Page* page = m_frame->page())
2118         page->progress()->progressStarted(m_frame);
2119     m_client->dispatchDidStartProvisionalLoad();
2120 }
2121
2122 void FrameLoader::setupForReplace()
2123 {
2124     setState(FrameStateProvisional);
2125     m_provisionalDocumentLoader = m_documentLoader;
2126     m_documentLoader = 0;
2127     detachChildren();
2128 }
2129
2130 void FrameLoader::setupForReplaceByMIMEType(const String& newMIMEType)
2131 {
2132     activeDocumentLoader()->setupForReplaceByMIMEType(newMIMEType);
2133 }
2134
2135 void FrameLoader::loadFrameRequestWithFormAndValues(const FrameLoadRequest& request, bool lockHistory, bool lockBackForwardList, Event* event,
2136     HTMLFormElement* submitForm, const HashMap<String, String>& formValues)
2137 {
2138     RefPtr<FormState> formState;
2139     if (submitForm)
2140         formState = FormState::create(submitForm, formValues, m_frame);
2141     
2142     KURL url = request.resourceRequest().url();
2143
2144     String referrer;
2145     String argsReferrer = request.resourceRequest().httpReferrer();
2146     if (!argsReferrer.isEmpty())
2147         referrer = argsReferrer;
2148     else
2149         referrer = m_outgoingReferrer;
2150
2151     ASSERT(frame()->document());
2152     if (url.protocolIs("file")) {
2153         if (!canLoad(url, String(), frame()->document()) && !canLoad(url, referrer)) {
2154             FrameLoader::reportLocalLoadFailed(m_frame, url.string());
2155             return;
2156         }
2157     }
2158
2159     if (shouldHideReferrer(url, referrer))
2160         referrer = String();
2161     
2162     FrameLoadType loadType;
2163     if (request.resourceRequest().cachePolicy() == ReloadIgnoringCacheData)
2164         loadType = FrameLoadTypeReload;
2165     else if (lockBackForwardList)
2166         loadType = FrameLoadTypeRedirectWithLockedBackForwardList;
2167     else
2168         loadType = FrameLoadTypeStandard;
2169
2170     if (request.resourceRequest().httpMethod() == "POST")
2171         loadPostRequest(request.resourceRequest(), referrer, request.frameName(), lockHistory, loadType, event, formState.release());
2172     else
2173         loadURL(request.resourceRequest().url(), referrer, request.frameName(), lockHistory, loadType, event, formState.release());
2174
2175     Frame* targetFrame = findFrameForNavigation(request.frameName());
2176     if (targetFrame && targetFrame != m_frame)
2177         if (Page* page = targetFrame->page())
2178             page->chrome()->focus();
2179 }
2180
2181 void FrameLoader::loadURL(const KURL& newURL, const String& referrer, const String& frameName, bool lockHistory, FrameLoadType newLoadType,
2182     Event* event, PassRefPtr<FormState> prpFormState)
2183 {
2184     RefPtr<FormState> formState = prpFormState;
2185     bool isFormSubmission = formState;
2186     
2187     ResourceRequest request(newURL);
2188     if (!referrer.isEmpty()) {
2189         request.setHTTPReferrer(referrer);
2190         RefPtr<SecurityOrigin> referrerOrigin = SecurityOrigin::createFromString(referrer);
2191         addHTTPOriginIfNeeded(request, referrerOrigin->toString());
2192     }
2193     addExtraFieldsToRequest(request, newLoadType, true, event || isFormSubmission);
2194     if (newLoadType == FrameLoadTypeReload || newLoadType == FrameLoadTypeReloadFromOrigin)
2195         request.setCachePolicy(ReloadIgnoringCacheData);
2196
2197     ASSERT(newLoadType != FrameLoadTypeSame);
2198
2199     NavigationAction action(newURL, newLoadType, isFormSubmission, event);
2200
2201     if (!frameName.isEmpty()) {
2202         if (Frame* targetFrame = findFrameForNavigation(frameName))
2203             targetFrame->loader()->loadURL(newURL, referrer, String(), lockHistory, newLoadType, event, formState);
2204         else
2205             checkNewWindowPolicy(action, request, formState, frameName);
2206         return;
2207     }
2208
2209     RefPtr<DocumentLoader> oldDocumentLoader = m_documentLoader;
2210
2211     bool sameURL = shouldTreatURLAsSameAsCurrent(newURL);
2212     
2213     // Make sure to do scroll to anchor processing even if the URL is
2214     // exactly the same so pages with '#' links and DHTML side effects
2215     // work properly.
2216     if (shouldScrollToAnchor(isFormSubmission, newLoadType, newURL)) {
2217         oldDocumentLoader->setTriggeringAction(action);
2218         stopPolicyCheck();
2219         checkNavigationPolicy(request, oldDocumentLoader.get(), formState,
2220             callContinueFragmentScrollAfterNavigationPolicy, this);
2221     } else {
2222         // must grab this now, since this load may stop the previous load and clear this flag
2223         bool isRedirect = m_quickRedirectComing;
2224         loadWithNavigationAction(request, action, lockHistory, newLoadType, formState);
2225         if (isRedirect) {
2226             m_quickRedirectComing = false;
2227             if (m_provisionalDocumentLoader)
2228                 m_provisionalDocumentLoader->setIsClientRedirect(true);
2229         } else if (sameURL)
2230             // Example of this case are sites that reload the same URL with a different cookie
2231             // driving the generated content, or a master frame with links that drive a target
2232             // frame, where the user has clicked on the same link repeatedly.
2233             m_loadType = FrameLoadTypeSame;
2234     }
2235 }
2236
2237 void FrameLoader::load(const ResourceRequest& request, bool lockHistory)
2238 {
2239     load(request, SubstituteData(), lockHistory);
2240 }
2241
2242 void FrameLoader::load(const ResourceRequest& request, const SubstituteData& substituteData, bool lockHistory)
2243 {
2244     if (m_inStopAllLoaders)
2245         return;
2246         
2247     // FIXME: is this the right place to reset loadType? Perhaps this should be done after loading is finished or aborted.
2248     m_loadType = FrameLoadTypeStandard;
2249     RefPtr<DocumentLoader> loader = m_client->createDocumentLoader(request, substituteData);
2250     if (lockHistory && m_documentLoader)
2251         loader->setClientRedirectSourceForHistory(m_documentLoader->didCreateGlobalHistoryEntry() ? m_documentLoader->urlForHistory() : m_documentLoader->clientRedirectSourceForHistory());
2252     load(loader.get());
2253 }
2254
2255 void FrameLoader::load(const ResourceRequest& request, const String& frameName, bool lockHistory)
2256 {
2257     if (frameName.isEmpty()) {
2258         load(request, lockHistory);
2259         return;
2260     }
2261
2262     Frame* frame = findFrameForNavigation(frameName);
2263     if (frame) {
2264         frame->loader()->load(request, lockHistory);
2265         return;
2266     }
2267
2268     checkNewWindowPolicy(NavigationAction(request.url(), NavigationTypeOther), request, 0, frameName);
2269 }
2270
2271 void FrameLoader::loadWithNavigationAction(const ResourceRequest& request, const NavigationAction& action, bool lockHistory, FrameLoadType type, PassRefPtr<FormState> formState)
2272 {
2273     RefPtr<DocumentLoader> loader = m_client->createDocumentLoader(request, SubstituteData());
2274     if (lockHistory && m_documentLoader)
2275         loader->setClientRedirectSourceForHistory(m_documentLoader->didCreateGlobalHistoryEntry() ? m_documentLoader->urlForHistory() : m_documentLoader->clientRedirectSourceForHistory());
2276
2277     loader->setTriggeringAction(action);
2278     if (m_documentLoader)
2279         loader->setOverrideEncoding(m_documentLoader->overrideEncoding());
2280
2281     loadWithDocumentLoader(loader.get(), type, formState);
2282 }
2283
2284 void FrameLoader::load(DocumentLoader* newDocumentLoader)
2285 {
2286     ResourceRequest& r = newDocumentLoader->request();
2287     addExtraFieldsToMainResourceRequest(r);
2288     FrameLoadType type;
2289
2290     if (shouldTreatURLAsSameAsCurrent(newDocumentLoader->originalRequest().url())) {
2291         r.setCachePolicy(ReloadIgnoringCacheData);
2292         type = FrameLoadTypeSame;
2293     } else
2294         type = FrameLoadTypeStandard;
2295
2296     if (m_documentLoader)
2297         newDocumentLoader->setOverrideEncoding(m_documentLoader->overrideEncoding());
2298     
2299     // When we loading alternate content for an unreachable URL that we're
2300     // visiting in the history list, we treat it as a reload so the history list 
2301     // is appropriately maintained.
2302     //
2303     // FIXME: This seems like a dangerous overloading of the meaning of "FrameLoadTypeReload" ...
2304     // shouldn't a more explicit type of reload be defined, that means roughly 
2305     // "load without affecting history" ? 
2306     if (shouldReloadToHandleUnreachableURL(newDocumentLoader)) {
2307         ASSERT(type == FrameLoadTypeStandard);
2308         type = FrameLoadTypeReload;
2309     }
2310
2311     loadWithDocumentLoader(newDocumentLoader, type, 0);
2312 }
2313
2314 void FrameLoader::loadWithDocumentLoader(DocumentLoader* loader, FrameLoadType type, PassRefPtr<FormState> prpFormState)
2315 {
2316     ASSERT(m_client->hasWebView());
2317
2318     // Unfortunately the view must be non-nil, this is ultimately due
2319     // to parser requiring a FrameView.  We should fix this dependency.
2320
2321     ASSERT(m_frame->view());
2322
2323     m_policyLoadType = type;
2324     RefPtr<FormState> formState = prpFormState;
2325     bool isFormSubmission = formState;
2326
2327     const KURL& newURL = loader->request().url();
2328
2329     if (shouldScrollToAnchor(isFormSubmission, m_policyLoadType, newURL)) {
2330         RefPtr<DocumentLoader> oldDocumentLoader = m_documentLoader;
2331         NavigationAction action(newURL, m_policyLoadType, isFormSubmission);
2332
2333         oldDocumentLoader->setTriggeringAction(action);
2334         stopPolicyCheck();
2335         checkNavigationPolicy(loader->request(), oldDocumentLoader.get(), formState,
2336             callContinueFragmentScrollAfterNavigationPolicy, this);
2337     } else {
2338         if (Frame* parent = m_frame->tree()->parent())
2339             loader->setOverrideEncoding(parent->loader()->documentLoader()->overrideEncoding());
2340
2341         stopPolicyCheck();
2342         setPolicyDocumentLoader(loader);
2343
2344         checkNavigationPolicy(loader->request(), loader, formState,
2345             callContinueLoadAfterNavigationPolicy, this);
2346     }
2347 }
2348
2349 bool FrameLoader::canLoad(const KURL& url, const String& referrer, const Document* doc)
2350 {
2351     // We can always load any URL that isn't considered local (e.g. http URLs)
2352     if (!shouldTreatURLAsLocal(url.string()))
2353         return true;
2354
2355     // If we were provided a document, we let its local file policy dictate the result,
2356     // otherwise we allow local loads only if the supplied referrer is also local.
2357     if (doc)
2358         return doc->securityOrigin()->canLoadLocalResources();
2359     else if (!referrer.isEmpty())
2360         return shouldTreatURLAsLocal(referrer);
2361     else
2362         return false;
2363 }
2364
2365 void FrameLoader::reportLocalLoadFailed(Frame* frame, const String& url)
2366 {
2367     ASSERT(!url.isEmpty());
2368     if (!frame)
2369         return;
2370
2371     frame->domWindow()->console()->addMessage(JSMessageSource, ErrorMessageLevel, "Not allowed to load local resource: " + url, 0, String());
2372 }
2373
2374 bool FrameLoader::shouldHideReferrer(const KURL& url, const String& referrer)
2375 {
2376     bool referrerIsSecureURL = protocolIs(referrer, "https");
2377     bool referrerIsWebURL = referrerIsSecureURL || protocolIs(referrer, "http");
2378
2379     if (!referrerIsWebURL)
2380         return true;
2381
2382     if (!referrerIsSecureURL)
2383         return false;
2384
2385     bool URLIsSecureURL = url.protocolIs("https");
2386
2387     return !URLIsSecureURL;
2388 }
2389
2390 const ResourceRequest& FrameLoader::initialRequest() const
2391 {
2392     return activeDocumentLoader()->originalRequest();
2393 }
2394
2395 void FrameLoader::receivedData(const char* data, int length)
2396 {
2397     activeDocumentLoader()->receivedData(data, length);
2398 }
2399
2400 void FrameLoader::handleUnimplementablePolicy(const ResourceError& error)
2401 {
2402     m_delegateIsHandlingUnimplementablePolicy = true;
2403     m_client->dispatchUnableToImplementPolicy(error);
2404     m_delegateIsHandlingUnimplementablePolicy = false;
2405 }
2406
2407 void FrameLoader::cannotShowMIMEType(const ResourceResponse& response)
2408 {
2409     handleUnimplementablePolicy(m_client->cannotShowMIMETypeError(response));
2410 }
2411
2412 ResourceError FrameLoader::interruptionForPolicyChangeError(const ResourceRequest& request)
2413 {
2414     return m_client->interruptForPolicyChangeError(request);
2415 }
2416
2417 void FrameLoader::checkNavigationPolicy(const ResourceRequest& newRequest, NavigationPolicyDecisionFunction function, void* argument)
2418 {
2419     checkNavigationPolicy(newRequest, activeDocumentLoader(), 0, function, argument);
2420 }
2421
2422 void FrameLoader::checkContentPolicy(const String& MIMEType, ContentPolicyDecisionFunction function, void* argument)
2423 {
2424     ASSERT(activeDocumentLoader());
2425     
2426     // Always show content with valid substitute data.
2427     if (activeDocumentLoader()->substituteData().isValid()) {
2428         function(argument, PolicyUse);
2429         return;
2430     }
2431
2432 #if ENABLE(FTPDIR)
2433     // Respect the hidden FTP Directory Listing pref so it can be tested even if the policy delegate might otherwise disallow it
2434     Settings* settings = m_frame->settings();
2435     if (settings && settings->forceFTPDirectoryListings() && MIMEType == "application/x-ftp-directory") {
2436         function(argument, PolicyUse);
2437         return;
2438     }
2439 #endif
2440
2441     m_policyCheck.set(function, argument);
2442     m_client->dispatchDecidePolicyForMIMEType(&FrameLoader::continueAfterContentPolicy,
2443         MIMEType, activeDocumentLoader()->request());
2444 }
2445
2446 bool FrameLoader::shouldReloadToHandleUnreachableURL(DocumentLoader* docLoader)
2447 {
2448     KURL unreachableURL = docLoader->unreachableURL();
2449
2450     if (unreachableURL.isEmpty())
2451         return false;
2452
2453     if (!isBackForwardLoadType(m_policyLoadType))
2454         return false;
2455
2456     // We only treat unreachableURLs specially during the delegate callbacks
2457     // for provisional load errors and navigation policy decisions. The former
2458     // case handles well-formed URLs that can't be loaded, and the latter
2459     // case handles malformed URLs and unknown schemes. Loading alternate content
2460     // at other times behaves like a standard load.
2461     DocumentLoader* compareDocumentLoader = 0;
2462     if (m_delegateIsDecidingNavigationPolicy || m_delegateIsHandlingUnimplementablePolicy)
2463         compareDocumentLoader = m_policyDocumentLoader.get();
2464     else if (m_delegateIsHandlingProvisionalLoadError)
2465         compareDocumentLoader = m_provisionalDocumentLoader.get();
2466
2467     return compareDocumentLoader && unreachableURL == compareDocumentLoader->request().url();
2468 }
2469
2470 void FrameLoader::reloadWithOverrideEncoding(const String& encoding)
2471 {
2472     if (!m_documentLoader)
2473         return;
2474
2475     ResourceRequest request = m_documentLoader->request();
2476     KURL unreachableURL = m_documentLoader->unreachableURL();
2477     if (!unreachableURL.isEmpty())
2478         request.setURL(unreachableURL);
2479
2480     request.setCachePolicy(ReturnCacheDataElseLoad);
2481
2482     RefPtr<DocumentLoader> loader = m_client->createDocumentLoader(request, SubstituteData());
2483     setPolicyDocumentLoader(loader.get());
2484
2485     loader->setOverrideEncoding(encoding);
2486
2487     loadWithDocumentLoader(loader.get(), FrameLoadTypeReload, 0);
2488 }
2489
2490 void FrameLoader::reload(bool endToEndReload)
2491 {
2492     if (!m_documentLoader)
2493         return;
2494
2495     // If a window is created by javascript, its main frame can have an empty but non-nil URL.
2496     // Reloading in this case will lose the current contents (see 4151001).
2497     if (m_documentLoader->request().url().isEmpty())
2498         return;
2499
2500     ResourceRequest initialRequest = m_documentLoader->request();
2501
2502     // Replace error-page URL with the URL we were trying to reach.
2503     KURL unreachableURL = m_documentLoader->unreachableURL();
2504     if (!unreachableURL.isEmpty())
2505         initialRequest.setURL(unreachableURL);
2506     
2507     // Create a new document loader for the reload, this will become m_documentLoader eventually,
2508     // but first it has to be the "policy" document loader, and then the "provisional" document loader.
2509     RefPtr<DocumentLoader> loader = m_client->createDocumentLoader(initialRequest, SubstituteData());
2510
2511     ResourceRequest& request = loader->request();
2512
2513     // FIXME: We don't have a mechanism to revalidate the main resource without reloading at the moment.
2514     request.setCachePolicy(ReloadIgnoringCacheData);
2515
2516     // If we're about to re-post, set up action so the application can warn the user.
2517     if (request.httpMethod() == "POST")
2518         loader->setTriggeringAction(NavigationAction(request.url(), NavigationTypeFormResubmitted));
2519
2520     loader->setOverrideEncoding(m_documentLoader->overrideEncoding());
2521     
2522     loadWithDocumentLoader(loader.get(), endToEndReload ? FrameLoadTypeReloadFromOrigin : FrameLoadTypeReload, 0);
2523 }
2524
2525 static bool canAccessAncestor(const SecurityOrigin* activeSecurityOrigin, Frame* targetFrame)
2526 {
2527     // targetFrame can be NULL when we're trying to navigate a top-level frame
2528     // that has a NULL opener.
2529     if (!targetFrame)
2530         return false;
2531
2532     for (Frame* ancestorFrame = targetFrame; ancestorFrame; ancestorFrame = ancestorFrame->tree()->parent()) {
2533         Document* ancestorDocument = ancestorFrame->document();
2534         if (!ancestorDocument)
2535             return true;
2536
2537         const SecurityOrigin* ancestorSecurityOrigin = ancestorDocument->securityOrigin();
2538         if (activeSecurityOrigin->canAccess(ancestorSecurityOrigin))
2539             return true;
2540     }
2541
2542     return false;
2543 }
2544
2545 bool FrameLoader::shouldAllowNavigation(Frame* targetFrame) const
2546 {
2547     // The navigation change is safe if the active frame is:
2548     //   - in the same security origin as the target or one of the target's
2549     //     ancestors.
2550     //
2551     // Or the target frame is:
2552     //   - a top-level frame in the frame hierarchy and the active frame can
2553     //     navigate the target frame's opener per above.
2554
2555     if (!targetFrame)
2556         return true;
2557
2558     // Performance optimization.
2559     if (m_frame == targetFrame)
2560         return true;
2561
2562     // Let a frame navigate the top-level window that contains it.  This is
2563     // important to allow because it lets a site "frame-bust" (escape from a
2564     // frame created by another web site).
2565     if (targetFrame == m_frame->tree()->top())
2566         return true;
2567
2568     Document* activeDocument = m_frame->document();
2569     ASSERT(activeDocument);
2570     const SecurityOrigin* activeSecurityOrigin = activeDocument->securityOrigin();
2571
2572     // For top-level windows, check the opener.
2573     if (!targetFrame->tree()->parent() && canAccessAncestor(activeSecurityOrigin, targetFrame->loader()->opener()))
2574         return true;
2575
2576     // In general, check the frame's ancestors.
2577     if (canAccessAncestor(activeSecurityOrigin, targetFrame))
2578         return true;
2579
2580     Settings* settings = targetFrame->settings();
2581     if (settings && !settings->privateBrowsingEnabled()) {
2582         Document* targetDocument = targetFrame->document();
2583         // FIXME: this error message should contain more specifics of why the navigation change is not allowed.
2584         String message = String::format("Unsafe JavaScript attempt to initiate a navigation change for frame with URL %s from frame with URL %s.\n",
2585             targetDocument->url().string().utf8().data(), activeDocument->url().string().utf8().data());
2586
2587         // FIXME: should we print to the console of the activeFrame as well?
2588         targetFrame->domWindow()->console()->addMessage(JSMessageSource, ErrorMessageLevel, message, 1, String());
2589     }
2590     
2591     return false;
2592 }
2593
2594 void FrameLoader::stopLoadingSubframes()
2595 {
2596     for (RefPtr<Frame> child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
2597         child->loader()->stopAllLoaders();
2598 }
2599
2600 void FrameLoader::stopAllLoaders()
2601 {
2602     // If this method is called from within this method, infinite recursion can occur (3442218). Avoid this.
2603     if (m_inStopAllLoaders)
2604         return;
2605
2606     m_inStopAllLoaders = true;
2607
2608     stopPolicyCheck();
2609
2610     stopLoadingSubframes();
2611     if (m_provisionalDocumentLoader)
2612         m_provisionalDocumentLoader->stopLoading();
2613     if (m_documentLoader)
2614         m_documentLoader->stopLoading();
2615
2616     setProvisionalDocumentLoader(0);
2617     
2618     if (m_documentLoader)
2619         m_documentLoader->clearArchiveResources();
2620
2621     m_inStopAllLoaders = false;    
2622 }
2623
2624 void FrameLoader::stopForUserCancel(bool deferCheckLoadComplete)
2625 {
2626     stopAllLoaders();
2627     
2628     if (deferCheckLoadComplete)
2629         scheduleCheckLoadComplete();
2630     else if (m_frame->page())
2631         checkLoadComplete();
2632 }
2633
2634 DocumentLoader* FrameLoader::activeDocumentLoader() const
2635 {
2636     if (m_state == FrameStateProvisional)
2637         return m_provisionalDocumentLoader.get();
2638     return m_documentLoader.get();
2639 }
2640
2641 bool FrameLoader::isLoading() const
2642 {
2643     DocumentLoader* docLoader = activeDocumentLoader();
2644     if (!docLoader)
2645         return false;
2646     return docLoader->isLoadingMainResource() || docLoader->isLoadingSubresources() || docLoader->isLoadingPlugIns();
2647 }
2648
2649 bool FrameLoader::frameHasLoaded() const
2650 {
2651     return m_committedFirstRealDocumentLoad || (m_provisionalDocumentLoader && !m_creatingInitialEmptyDocument); 
2652 }
2653
2654 void FrameLoader::setDocumentLoader(DocumentLoader* loader)
2655 {
2656     if (!loader && !m_documentLoader)
2657         return;
2658     
2659     ASSERT(loader != m_documentLoader);
2660     ASSERT(!loader || loader->frameLoader() == this);
2661
2662     m_client->prepareForDataSourceReplacement();
2663     detachChildren();
2664     if (m_documentLoader)
2665         m_documentLoader->detachFromFrame();
2666
2667     m_documentLoader = loader;
2668 }
2669
2670 void FrameLoader::setPolicyDocumentLoader(DocumentLoader* loader)
2671 {
2672     if (m_policyDocumentLoader == loader)
2673         return;
2674
2675     ASSERT(m_frame);
2676     if (loader)
2677         loader->setFrame(m_frame);
2678     if (m_policyDocumentLoader
2679             && m_policyDocumentLoader != m_provisionalDocumentLoader
2680             && m_policyDocumentLoader != m_documentLoader)
2681         m_policyDocumentLoader->detachFromFrame();
2682
2683     m_policyDocumentLoader = loader;
2684 }
2685
2686 void FrameLoader::setProvisionalDocumentLoader(DocumentLoader* loader)
2687 {
2688     ASSERT(!loader || !m_provisionalDocumentLoader);
2689     ASSERT(!loader || loader->frameLoader() == this);
2690
2691     if (m_provisionalDocumentLoader && m_provisionalDocumentLoader != m_documentLoader)
2692         m_provisionalDocumentLoader->detachFromFrame();
2693
2694     m_provisionalDocumentLoader = loader;
2695 }
2696
2697 double FrameLoader::timeOfLastCompletedLoad()
2698 {
2699     return storedTimeOfLastCompletedLoad;
2700 }
2701
2702 void FrameLoader::setState(FrameState newState)
2703 {    
2704     m_state = newState;
2705     
2706     if (newState == FrameStateProvisional)
2707         provisionalLoadStarted();
2708     else if (newState == FrameStateComplete) {
2709         frameLoadCompleted();
2710         storedTimeOfLastCompletedLoad = currentTime();
2711         if (m_documentLoader)
2712             m_documentLoader->stopRecordingResponses();
2713     }
2714 }
2715
2716 void FrameLoader::clearProvisionalLoad()
2717 {
2718     setProvisionalDocumentLoader(0);
2719     if (Page* page = m_frame->page())
2720         page->progress()->progressCompleted(m_frame);
2721     setState(FrameStateComplete);
2722 }
2723
2724 void FrameLoader::markLoadComplete()
2725 {
2726     setState(FrameStateComplete);
2727 }
2728
2729 void FrameLoader::commitProvisionalLoad(PassRefPtr<CachedPage> prpCachedPage)
2730 {
2731     RefPtr<CachedPage> cachedPage = prpCachedPage;
2732     RefPtr<DocumentLoader> pdl = m_provisionalDocumentLoader;
2733
2734     LOG(Loading, "WebCoreLoading %s: About to commit provisional load from previous URL %s", m_frame->tree()->name().string().utf8().data(), m_URL.string().utf8().data());
2735
2736     // Check to see if we need to cache the page we are navigating away from into the back/forward cache.
2737     // We are doing this here because we know for sure that a new page is about to be loaded.
2738     cachePageForHistoryItem(m_currentHistoryItem.get());
2739     
2740     if (m_loadType != FrameLoadTypeReplace)
2741         closeOldDataSources();
2742     
2743     if (!cachedPage && !m_creatingInitialEmptyDocument)
2744         m_client->makeRepresentation(pdl.get());
2745     
2746     transitionToCommitted(cachedPage);
2747     
2748     // Call clientRedirectCancelledOrFinished() here so that the frame load delegate is notified that the redirect's
2749     // status has changed, if there was a redirect.  The frame load delegate may have saved some state about
2750     // the redirect in its -webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:.  Since we are
2751     // just about to commit a new page, there cannot possibly be a pending redirect at this point.
2752     if (m_sentRedirectNotification)
2753         clientRedirectCancelledOrFinished(false);
2754     
2755     if (cachedPage && cachedPage->document()) {
2756         open(*cachedPage);
2757         cachedPage->clear();
2758     } else {        
2759         KURL url = pdl->substituteData().responseURL();
2760         if (url.isEmpty())
2761             url = pdl->url();
2762         if (url.isEmpty())
2763             url = pdl->responseURL();
2764         if (url.isEmpty())
2765             url = blankURL();
2766
2767         didOpenURL(url);
2768     }
2769
2770     LOG(Loading, "WebCoreLoading %s: Finished committing provisional load to URL %s", m_frame->tree()->name().string().utf8().data(), m_URL.string().utf8().data());
2771
2772     if (m_loadType == FrameLoadTypeStandard && m_documentLoader->isClientRedirect())
2773         updateHistoryForClientRedirect();
2774
2775     if (m_documentLoader->isLoadingFromCachedPage()) {
2776         m_frame->document()->documentDidBecomeActive();
2777         
2778         // Force a layout to update view size and thereby update scrollbars.
2779         m_client->forceLayout();
2780
2781         const ResponseVector& responses = m_documentLoader->responses();
2782         size_t count = responses.size();
2783         for (size_t i = 0; i < count; i++) {
2784             const ResourceResponse& response = responses[i];
2785             // FIXME: If the WebKit client changes or cancels the request, this is not respected.
2786             ResourceError error;
2787             unsigned long identifier;
2788             ResourceRequest request(response.url());
2789             requestFromDelegate(request, identifier, error);
2790             // FIXME: If we get a resource with more than 2B bytes, this code won't do the right thing.
2791             // However, with today's computers and networking speeds, this won't happen in practice.
2792             // Could be an issue with a giant local file.
2793             sendRemainingDelegateMessages(identifier, response, static_cast<int>(response.expectedContentLength()), error);
2794         }
2795         
2796         pageCache()->remove(m_currentHistoryItem.get());
2797
2798         m_documentLoader->setPrimaryLoadComplete(true);
2799
2800         // FIXME: Why only this frame and not parent frames?
2801         checkLoadCompleteForThisFrame();
2802     }
2803 }
2804
2805 void FrameLoader::transitionToCommitted(PassRefPtr<CachedPage> cachedPage)
2806 {
2807     ASSERT(m_client->hasWebView());
2808     ASSERT(m_state == FrameStateProvisional);
2809
2810     if (m_state != FrameStateProvisional)
2811         return;
2812
2813     m_client->setCopiesOnScroll();
2814     updateHistoryForCommit();
2815
2816     // The call to closeURL() invokes the unload event handler, which can execute arbitrary
2817     // JavaScript. If the script initiates a new load, we need to abandon the current load,
2818     // or the two will stomp each other.
2819     DocumentLoader* pdl = m_provisionalDocumentLoader.get();
2820     if (m_documentLoader)
2821         closeURL();
2822     if (pdl != m_provisionalDocumentLoader)
2823         return;
2824
2825     // Nothing else can interupt this commit - set the Provisional->Committed transition in stone
2826     if (m_documentLoader)
2827         m_documentLoader->stopLoadingSubresources();
2828     if (m_documentLoader)
2829         m_documentLoader->stopLoadingPlugIns();
2830
2831     setDocumentLoader(m_provisionalDocumentLoader.get());
2832     setProvisionalDocumentLoader(0);
2833     setState(FrameStateCommittedPage);
2834
2835     // Handle adding the URL to the back/forward list.
2836     DocumentLoader* dl = m_documentLoader.get();
2837     String ptitle = dl->title(); 
2838
2839     switch (m_loadType) {
2840         case FrameLoadTypeForward:
2841         case FrameLoadTypeBack:
2842         case FrameLoadTypeIndexedBackForward:
2843             if (Page* page = m_frame->page())
2844                 if (page->backForwardList()) {
2845                     updateHistoryForBackForwardNavigation();
2846
2847                     // Create a document view for this document, or used the cached view.
2848                     if (cachedPage) {
2849                         DocumentLoader* cachedDocumentLoader = cachedPage->documentLoader();
2850                         ASSERT(cachedDocumentLoader);
2851                         cachedDocumentLoader->setFrame(m_frame);
2852                         m_client->transitionToCommittedFromCachedFrame(cachedPage->cachedMainFrame());
2853                         
2854                     } else
2855                         m_client->transitionToCommittedForNewPage();
2856                 }
2857             break;
2858
2859         case FrameLoadTypeReload:
2860         case FrameLoadTypeReloadFromOrigin:
2861         case FrameLoadTypeSame:
2862         case FrameLoadTypeReplace:
2863             updateHistoryForReload();
2864             m_client->transitionToCommittedForNewPage();
2865             break;
2866
2867         case FrameLoadTypeStandard:
2868             updateHistoryForStandardLoad();
2869 #ifndef BUILDING_ON_TIGER
2870             // This code was originally added for a Leopard performance imporvement. We decided to 
2871             // ifdef it to fix correctness issues on Tiger documented in <rdar://problem/5441823>.
2872             if (m_frame->view())
2873                 m_frame->view()->setScrollbarsSuppressed(true);
2874 #endif
2875             m_client->transitionToCommittedForNewPage();
2876             break;
2877
2878         case FrameLoadTypeRedirectWithLockedBackForwardList:
2879             updateHistoryForRedirectWithLockedBackForwardList();
2880             m_client->transitionToCommittedForNewPage();
2881             break;
2882
2883         // FIXME Remove this check when dummy ds is removed (whatever "dummy ds" is).
2884         // An exception should be thrown if we're in the FrameLoadTypeUninitialized state.
2885         default:
2886             ASSERT_NOT_REACHED();
2887     }
2888
2889     m_responseMIMEType = dl->responseMIMEType();
2890
2891     // Tell the client we've committed this URL.
2892     ASSERT(m_frame->view());
2893
2894     if (m_creatingInitialEmptyDocument)
2895         return;
2896     
2897     m_committedFirstRealDocumentLoad = true;
2898
2899     // For non-cached HTML pages, these methods are called in FrameLoader::begin.
2900     if (cachedPage || !m_client->hasHTMLView()) {
2901         dispatchDidCommitLoad(); 
2902             
2903         // If we have a title let the WebView know about it. 
2904         if (!ptitle.isNull()) 
2905             m_client->dispatchDidReceiveTitle(ptitle);         
2906     }
2907 }
2908
2909 void FrameLoader::clientRedirectCancelledOrFinished(bool cancelWithLoadInProgress)
2910 {
2911     // Note that -webView:didCancelClientRedirectForFrame: is called on the frame load delegate even if
2912     // the redirect succeeded.  We should either rename this API, or add a new method, like
2913     // -webView:didFinishClientRedirectForFrame:
2914     m_client->dispatchDidCancelClientRedirect();
2915
2916     if (!cancelWithLoadInProgress)
2917         m_quickRedirectComing = false;
2918
2919     m_sentRedirectNotification = false;
2920 }
2921
2922 void FrameLoader::clientRedirected(const KURL& url, double seconds, double fireDate, bool lockBackForwardList, bool isJavaScriptFormAction)
2923 {
2924     m_client->dispatchWillPerformClientRedirect(url, seconds, fireDate);
2925     
2926     // Remember that we sent a redirect notification to the frame load delegate so that when we commit
2927     // the next provisional load, we can send a corresponding -webView:didCancelClientRedirectForFrame:
2928     m_sentRedirectNotification = true;
2929     
2930     // If a "quick" redirect comes in an, we set a special mode so we treat the next
2931     // load as part of the same navigation. If we don't have a document loader, we have
2932     // no "original" load on which to base a redirect, so we treat the redirect as a normal load.
2933     m_quickRedirectComing = lockBackForwardList && m_documentLoader && !isJavaScriptFormAction;
2934 }
2935
2936 #if ENABLE(WML)
2937 void FrameLoader::setForceReloadWmlDeck(bool reload)
2938 {
2939     m_forceReloadWmlDeck = reload;
2940 }
2941 #endif
2942
2943 bool FrameLoader::shouldReload(const KURL& currentURL, const KURL& destinationURL)
2944 {
2945 #if ENABLE(WML)
2946     // As for WML deck, sometimes it's supposed to be reloaded even if the same URL with fragment
2947     if (m_forceReloadWmlDeck)
2948         return true;
2949 #endif
2950
2951     // This function implements the rule: "Don't reload if navigating by fragment within
2952     // the same URL, but do reload if going to a new URL or to the same URL with no
2953     // fragment identifier at all."
2954     if (!destinationURL.hasRef())
2955         return true;
2956     return !equalIgnoringRef(currentURL, destinationURL);
2957 }
2958
2959 void FrameLoader::closeOldDataSources()
2960 {
2961     // FIXME: Is it important for this traversal to be postorder instead of preorder?
2962     // If so, add helpers for postorder traversal, and use them. If not, then lets not
2963     // use a recursive algorithm here.
2964     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
2965         child->loader()->closeOldDataSources();
2966     
2967     if (m_documentLoader)
2968         m_client->dispatchWillClose();
2969
2970     m_client->setMainFrameDocumentReady(false); // stop giving out the actual DOMDocument to observers
2971 }
2972
2973 void FrameLoader::open(CachedPage& cachedPage)
2974 {
2975     ASSERT(!m_frame->tree()->parent());
2976     ASSERT(m_frame->page());
2977     ASSERT(m_frame->page()->mainFrame() == m_frame);
2978
2979     cancelRedirection();
2980
2981     // We still have to close the previous part page.
2982     closeURL();
2983     
2984     // Delete old status bar messages (if it _was_ activated on last URL).
2985     if (m_frame->script()->isEnabled()) {
2986         m_frame->setJSStatusBarText(String());
2987         m_frame->setJSDefaultStatusBarText(String());
2988     }
2989
2990     open(*cachedPage.cachedMainFrame());
2991
2992     checkCompleted();
2993 }
2994
2995 void FrameLoader::open(CachedFrame& cachedFrame)
2996 {
2997     m_isComplete = false;
2998     
2999     // Don't re-emit the load event.
3000     m_didCallImplicitClose = true;
3001
3002     KURL url = cachedFrame.url();
3003
3004     if ((url.protocolIs("http") || url.protocolIs("https")) && !url.host().isEmpty() && url.path().isEmpty())
3005         url.setPath("/");
3006     
3007     m_URL = url;
3008     m_workingURL = url;
3009
3010     started();
3011
3012     clear();
3013
3014     Document* document = cachedFrame.document();
3015     ASSERT(document);
3016     document->setInPageCache(false);
3017
3018     m_needsClear = true;
3019     m_isComplete = false;
3020     m_didCallImplicitClose = false;
3021     m_outgoingReferrer = url.string();
3022
3023     FrameView* view = cachedFrame.view();
3024     
3025     // When navigating to a CachedFrame its FrameView should never be null.  If it is we'll crash in creative ways downstream.
3026     ASSERT(view);
3027     if (view)
3028         view->setWasScrolledByUser(false);
3029     m_frame->setView(view);
3030     
3031     m_frame->setDocument(document);
3032     m_frame->setDOMWindow(cachedFrame.domWindow());
3033     m_frame->domWindow()->setURL(document->url());
3034     m_frame->domWindow()->setSecurityOrigin(document->securityOrigin());
3035
3036     m_decoder = document->decoder();
3037
3038     updatePolicyBaseURL();
3039
3040     cachedFrame.restore();
3041 }
3042
3043 bool FrameLoader::isStopping() const
3044 {
3045     return activeDocumentLoader()->isStopping();
3046 }
3047
3048 void FrameLoader::finishedLoading()
3049 {
3050     // Retain because the stop may release the last reference to it.
3051     RefPtr<Frame> protect(m_frame);
3052
3053     RefPtr<DocumentLoader> dl = activeDocumentLoader();
3054     dl->finishedLoading();
3055     if (!dl->mainDocumentError().isNull() || !dl->frameLoader())
3056         return;
3057     dl->setPrimaryLoadComplete(true);
3058     m_client->dispatchDidLoadMainResource(dl.get());
3059     checkLoadComplete();
3060 }
3061
3062 bool FrameLoader::isHostedByObjectElement() const
3063 {
3064     HTMLFrameOwnerElement* owner = m_frame->ownerElement();
3065     return owner && owner->hasTagName(objectTag);
3066 }
3067
3068 bool FrameLoader::isLoadingMainFrame() const
3069 {
3070     Page* page = m_frame->page();
3071     return page && m_frame == page->mainFrame();
3072 }
3073
3074 bool FrameLoader::canShowMIMEType(const String& MIMEType) const
3075 {
3076     return m_client->canShowMIMEType(MIMEType);
3077 }
3078
3079 bool FrameLoader::representationExistsForURLScheme(const String& URLScheme)
3080 {
3081     return m_client->representationExistsForURLScheme(URLScheme);
3082 }
3083
3084 String FrameLoader::generatedMIMETypeForURLScheme(const String& URLScheme)
3085 {
3086     return m_client->generatedMIMETypeForURLScheme(URLScheme);
3087 }
3088
3089 void FrameLoader::cancelContentPolicyCheck()
3090 {
3091     m_client->cancelPolicyCheck();
3092     m_policyCheck.clear();
3093 }
3094
3095 void FrameLoader::didReceiveServerRedirectForProvisionalLoadForFrame()
3096 {
3097     m_client->dispatchDidReceiveServerRedirectForProvisionalLoad();
3098 }
3099
3100 void FrameLoader::finishedLoadingDocument(DocumentLoader* loader)
3101 {
3102     // FIXME: Platforms shouldn't differ here!
3103 #if PLATFORM(WIN) || PLATFORM(CHROMIUM)
3104     if (m_creatingInitialEmptyDocument)
3105         return;
3106 #endif
3107     
3108     // If loading a webarchive, run through webarchive machinery
3109     const String& responseMIMEType = loader->responseMIMEType();
3110
3111     // FIXME: Mac's FrameLoaderClient::finishedLoading() method does work that is required even with Archive loads
3112     // so we still need to call it.  Other platforms should only call finishLoading for non-archive loads
3113     // That work should be factored out so this #ifdef can be removed
3114 #if PLATFORM(MAC)
3115     m_client->finishedLoading(loader);
3116     if (!ArchiveFactory::isArchiveMimeType(responseMIMEType))
3117         return;
3118 #else
3119     if (!ArchiveFactory::isArchiveMimeType(responseMIMEType)) {
3120         m_client->finishedLoading(loader);
3121         return;
3122     }
3123 #endif
3124         
3125     RefPtr<Archive> archive(ArchiveFactory::create(loader->mainResourceData().get(), responseMIMEType));
3126     if (!archive)
3127         return;
3128
3129     loader->addAllArchiveResources(archive.get());
3130     
3131     ArchiveResource* mainResource = archive->mainResource();
3132     loader->setParsedArchiveData(mainResource->data());
3133     continueLoadWithData(mainResource->data(), mainResource->mimeType(), mainResource->textEncoding(), mainResource->url());
3134 }
3135
3136 bool FrameLoader::isReplacing() const
3137 {
3138     return m_loadType == FrameLoadTypeReplace;
3139 }
3140
3141 void FrameLoader::setReplacing()
3142 {
3143     m_loadType = FrameLoadTypeReplace;
3144 }
3145
3146 void FrameLoader::revertToProvisional(DocumentLoader* loader)
3147 {
3148     m_client->revertToProvisionalState(loader);
3149 }
3150
3151 bool FrameLoader::subframeIsLoading() const
3152 {
3153     // It's most likely that the last added frame is the last to load so we walk backwards.
3154     for (Frame* child = m_frame->tree()->lastChild(); child; child = child->tree()->previousSibling()) {
3155         FrameLoader* childLoader = child->loader();
3156         DocumentLoader* documentLoader = childLoader->documentLoader();
3157         if (documentLoader && documentLoader->isLoadingInAPISense())
3158             return true;
3159         documentLoader = childLoader->provisionalDocumentLoader();
3160         if (documentLoader && documentLoader->isLoadingInAPISense())
3161             return true;
3162     }
3163     return false;
3164 }
3165
3166 void FrameLoader::willChangeTitle(DocumentLoader* loader)
3167 {
3168     m_client->willChangeTitle(loader);
3169 }
3170
3171 FrameLoadType FrameLoader::loadType() const
3172 {
3173     return m_loadType;
3174 }
3175     
3176 CachePolicy FrameLoader::cachePolicy() const
3177 {
3178     if (m_isComplete)
3179         return CachePolicyVerify;
3180     
3181     if (m_loadType == FrameLoadTypeReloadFromOrigin || documentLoader()->request().cachePolicy() == ReloadIgnoringCacheData)
3182         return CachePolicyReload;
3183     
3184     if (Frame* parentFrame = m_frame->tree()->parent()) {
3185         CachePolicy parentCachePolicy = parentFrame->loader()->cachePolicy();
3186         if (parentCachePolicy != CachePolicyVerify)
3187             return parentCachePolicy;
3188     }
3189
3190     if (m_loadType == FrameLoadTypeReload)
3191         return CachePolicyRevalidate;
3192
3193     return CachePolicyVerify;
3194 }
3195
3196 void FrameLoader::stopPolicyCheck()
3197 {
3198     m_client->cancelPolicyCheck();
3199     PolicyCheck check = m_policyCheck;
3200     m_policyCheck.clear();
3201     check.cancel();
3202 }
3203
3204 void FrameLoader::checkLoadCompleteForThisFrame()
3205 {
3206     ASSERT(m_client->hasWebView());
3207
3208     switch (m_state) {
3209         case FrameStateProvisional: {
3210             if (m_delegateIsHandlingProvisionalLoadError)
3211                 return;
3212
3213             RefPtr<DocumentLoader> pdl = m_provisionalDocumentLoader;
3214             if (!pdl)
3215                 return;
3216                 
3217             // If we've received any errors we may be stuck in the provisional state and actually complete.
3218             const ResourceError& error = pdl->mainDocumentError();
3219             if (error.isNull())
3220                 return;
3221
3222             // Check all children first.
3223             RefPtr<HistoryItem> item;
3224             if (Page* page = m_frame->page())
3225                 if (isBackForwardLoadType(loadType()) && m_frame == page->mainFrame())
3226                     item = m_currentHistoryItem;
3227                 
3228             bool shouldReset = true;
3229             if (!pdl->isLoadingInAPISense()) {
3230                 m_delegateIsHandlingProvisionalLoadError = true;
3231                 m_client->dispatchDidFailProvisionalLoad(error);
3232                 m_delegateIsHandlingProvisionalLoadError = false;
3233
3234                 // FIXME: can stopping loading here possibly have any effect, if isLoading is false,
3235                 // which it must be to be in this branch of the if? And is it OK to just do a full-on
3236                 // stopAllLoaders instead of stopLoadingSubframes?
3237                 stopLoadingSubframes();
3238                 pdl->stopLoading();
3239
3240                 // Finish resetting the load state, but only if another load hasn't been started by the
3241                 // delegate callback.
3242                 if (pdl == m_provisionalDocumentLoader)
3243                     clearProvisionalLoad();
3244                 else if (m_provisionalDocumentLoader) {
3245                     KURL unreachableURL = m_provisionalDocumentLoader->unreachableURL();
3246                     if (!unreachableURL.isEmpty() && unreachableURL == pdl->request().url())
3247                         shouldReset = false;
3248                 }
3249             }
3250             if (shouldReset && item)
3251                 if (Page* page = m_frame->page()) {
3252                     page->backForwardList()->goToItem(item.get());
3253                     Settings* settings = m_frame->settings();
3254                     page->setGlobalHistoryItem((!settings || settings->privateBrowsingEnabled()) ? 0 : item.get());
3255                 }
3256             return;
3257         }
3258         
3259         case FrameStateCommittedPage: {
3260             DocumentLoader* dl = m_documentLoader.get();            
3261             if (!dl || dl->isLoadingInAPISense())
3262                 return;
3263
3264             markLoadComplete();
3265
3266             // FIXME: Is this subsequent work important if we already navigated away?
3267             // Maybe there are bugs because of that, or extra work we can skip because
3268             // the new page is ready.
3269
3270             m_client->forceLayoutForNonHTML();
3271              
3272             // If the user had a scroll point, scroll to it, overriding the anchor point if any.
3273             if (Page* page = m_frame->page())
3274                 if ((isBackForwardLoadType(m_loadType) || m_loadType == FrameLoadTypeReload || m_loadType == FrameLoadTypeReloadFromOrigin) && page->backForwardList())
3275                     restoreScrollPositionAndViewState();
3276
3277             if (m_creatingInitialEmptyDocument || !m_committedFirstRealDocumentLoad)
3278                 return;
3279
3280             const ResourceError& error = dl->mainDocumentError();
3281 #ifndef NDEBUG
3282             m_didDispatchDidCommitLoad = false;
3283 #endif
3284             if (!error.isNull())
3285                 m_client->dispatchDidFailLoad(error);
3286             else
3287                 m_client->dispatchDidFinishLoad();
3288
3289             if (Page* page = m_frame->page())
3290                 page->progress()->progressCompleted(m_frame);
3291             return;
3292         }
3293         
3294         case FrameStateComplete:
3295             frameLoadCompleted();
3296             return;
3297     }
3298
3299     ASSERT_NOT_REACHED();
3300 }
3301
3302 void FrameLoader::continueAfterContentPolicy(PolicyAction policy)
3303 {
3304     PolicyCheck check = m_policyCheck;
3305     m_policyCheck.clear();
3306     check.call(policy);
3307 }
3308
3309 void FrameLoader::continueLoadAfterWillSubmitForm(PolicyAction)
3310 {
3311     if (!m_provisionalDocumentLoader)
3312         return;
3313
3314     // DocumentLoader calls back to our prepareForLoadStart
3315     m_provisionalDocumentLoader->prepareForLoadStart();
3316     
3317     // The load might be cancelled inside of prepareForLoadStart(), nulling out the m_provisionalDocumentLoader, 
3318     // so we need to null check it again.
3319     if (!m_provisionalDocumentLoader)
3320         return;
3321
3322     DocumentLoader* activeDocLoader = activeDocumentLoader();
3323     if (activeDocLoader && activeDocLoader->isLoadingMainResource())
3324         return;
3325
3326     m_provisionalDocumentLoader->setLoadingFromCachedPage(false);
3327
3328     unsigned long identifier = 0;
3329
3330     if (Page* page = m_frame->page()) {
3331         identifier = page->progress()->createUniqueIdentifier();
3332         dispatchAssignIdentifierToInitialRequest(identifier, m_provisionalDocumentLoader.get(), m_provisionalDocumentLoader->originalRequest());
3333     }
3334
3335     if (!m_provisionalDocumentLoader->startLoadingMainResource(identifier))
3336         m_provisionalDocumentLoader->updateLoading();
3337 }
3338
3339 void FrameLoader::didFirstLayout()
3340 {
3341     if (Page* page = m_frame->page())
3342         if (isBackForwardLoadType(m_loadType) && page->backForwardList())
3343             restoreScrollPositionAndViewState();
3344
3345     m_firstLayoutDone = true;
3346     m_client->dispatchDidFirstLayout();
3347 }
3348
3349 void FrameLoader::didFirstVisuallyNonEmptyLayout()
3350 {
3351     m_client->dispatchDidFirstVisuallyNonEmptyLayout();
3352 }
3353
3354 void FrameLoader::frameLoadCompleted()
3355 {
3356     // Note: Can be called multiple times.
3357
3358     m_client->frameLoadCompleted();
3359
3360     // Even if already complete, we might have set a previous item on a frame that
3361     // didn't do any data loading on the past transaction. Make sure to clear these out.
3362     setPreviousHistoryItem(0);
3363
3364     // After a canceled provisional load, firstLayoutDone is false.
3365     // Reset it to true if we're displaying a page.
3366     if (m_documentLoader)
3367         m_firstLayoutDone = true;
3368 }
3369
3370 bool FrameLoader::firstLayoutDone() const
3371 {
3372     return m_firstLayoutDone;
3373 }
3374
3375 bool FrameLoader::isQuickRedirectComing() const
3376 {
3377     return m_quickRedirectComing;
3378 }
3379
3380 void FrameLoader::detachChildren()
3381 {
3382     // FIXME: Is it really necessary to do this in reverse order?
3383     Frame* previous;
3384     for (Frame* child = m_frame->tree()->lastChild(); child; child = previous) {
3385         previous = child->tree()->previousSibling();
3386         child->loader()->detachFromParent();
3387     }
3388 }
3389
3390 void FrameLoader::closeAndRemoveChild(Frame* child)
3391 {
3392     child->tree()->detachFromParent();
3393
3394     child->setView(0);
3395     if (child->ownerElement())
3396         child->page()->decrementFrameCount();
3397     child->pageDestroyed();
3398
3399     m_frame->tree()->removeChild(child);
3400 }
3401
3402 void FrameLoader::recursiveCheckLoadComplete()
3403 {
3404     Vector<RefPtr<Frame>, 10> frames;
3405     
3406     for (RefPtr<Frame> frame = m_frame->tree()->firstChild(); frame; frame = frame->tree()->nextSibling())
3407         frames.append(frame);
3408     
3409     unsigned size = frames.size();
3410     for (unsigned i = 0; i < size; i++)
3411         frames[i]->loader()->recursiveCheckLoadComplete();
3412     
3413     checkLoadCompleteForThisFrame();
3414 }
3415
3416 // Called every time a resource is completely loaded, or an error is received.
3417 void FrameLoader::checkLoadComplete()
3418 {
3419     ASSERT(m_client->hasWebView());
3420     
3421     // FIXME: Always traversing the entire frame tree is a bit inefficient, but 
3422     // is currently needed in order to null out the previous history item for all frames.
3423     if (Page* page = m_frame->page())
3424         page->mainFrame()->loader()->recursiveCheckLoadComplete();
3425 }
3426
3427 int FrameLoader::numPendingOrLoadingRequests(bool recurse) const
3428 {
3429     if (!recurse)
3430         return numRequests(m_frame->document());
3431
3432     int count = 0;
3433     for (Frame* frame = m_frame; frame; frame = frame->tree()->traverseNext(m_frame))
3434         count += numRequests(frame->document());
3435     return count;
3436 }
3437
3438 void FrameLoader::submitForm(const FrameLoadRequest& request, Event* event, bool lockHistory, bool lockBackForwardList)
3439 {
3440     // FIXME: We'd like to remove this altogether and fix the multiple form submission issue another way.
3441     // We do not want to submit more than one form from the same page,
3442     // nor do we want to submit a single form more than once.
3443     // This flag prevents these from happening; not sure how other browsers prevent this.
3444     // The flag is reset in each time we start handle a new mouse or key down event, and
3445     // also in setView since this part may get reused for a page from the back/forward cache.
3446     // The form multi-submit logic here is only needed when we are submitting a form that affects this frame.
3447     // FIXME: Frame targeting is only one of the ways the submission could end up doing something other
3448     // than replacing this frame's content, so this check is flawed. On the other hand, the check is hardly
3449     // needed any more now that we reset m_submittedFormURL on each mouse or key down event.
3450     Frame* target = m_frame->tree()->find(request.frameName());
3451     if (m_frame->tree()->isDescendantOf(target)) {
3452         if (m_submittedFormURL == request.resourceRequest().url())
3453             return;
3454         m_submittedFormURL = request.resourceRequest().url();
3455     }
3456
3457     loadFrameRequestWithFormAndValues(request, lockHistory, lockBackForwardList, event, m_formAboutToBeSubmitted.get(), m_formValuesAboutToBeSubmitted);
3458
3459     clearRecordedFormValues();
3460 }
3461
3462 String FrameLoader::userAgent(const KURL& url) const
3463 {
3464     return m_client->userAgent(url);
3465 }
3466
3467 void FrameLoader::tokenizerProcessedData()
3468 {
3469 //    ASSERT(m_frame->page());
3470 //    ASSERT(m_frame->document());
3471
3472     checkCompleted();
3473 }
3474
3475 void FrameLoader::handledOnloadEvents()
3476 {
3477     m_client->dispatchDidHandleOnloadEvents();
3478 }
3479
3480 void FrameLoader::frameDetached()
3481 {
3482     stopAllLoaders();
3483     m_frame->document()->stopActiveDOMObjects();
3484     detachFromParent();
3485 }
3486
3487 void FrameLoader::detachFromParent()
3488 {
3489     RefPtr<Frame> protect(m_frame);
3490
3491     closeURL();
3492     stopAllLoaders();
3493     saveScrollPositionAndViewStateToItem(currentHistoryItem());
3494     detachChildren();
3495
3496     if (Page* page = m_frame->page())
3497         page->inspectorController()->frameDetachedFromParent(m_frame);
3498
3499     m_client->detachedFromParent2();
3500     setDocumentLoader(0);
3501     m_client->detachedFromParent3();
3502     if (Frame* parent = m_frame->tree()->parent()) {
3503         parent->loader()->closeAndRemoveChild(m_frame);
3504         parent->loader()->scheduleCheckCompleted();
3505     } else {
3506         m_frame->setView(0);
3507         m_frame->pageDestroyed();
3508     }
3509 }
3510     
3511 void FrameLoader::addExtraFieldsToSubresourceRequest(ResourceRequest& request)
3512 {
3513     addExtraFieldsToRequest(request, m_loadType, false, false);
3514 }
3515
3516 void FrameLoader::addExtraFieldsToMainResourceRequest(ResourceRequest& request)
3517 {
3518     addExtraFieldsToRequest(request, m_loadType, true, false);
3519 }
3520
3521 void FrameLoader::addExtraFieldsToRequest(ResourceRequest& request, FrameLoadType loadType, bool mainResource, bool cookiePolicyURLFromRequest)
3522 {
3523     // Don't set the cookie policy URL if it's already been set.
3524     // But make sure to set it on all requests, as it has significance beyond the cookie policy for all protocols (<rdar://problem/6616664>).
3525     if (request.mainDocumentURL().isEmpty()) {
3526         if (mainResource && (isLoadingMainFrame() || cookiePolicyURLFromRequest))
3527             request.setMainDocumentURL(request.url());
3528         else if (Page* page = m_frame->page())
3529             request.setMainDocumentURL(page->mainFrame()->loader()->url());
3530     }
3531     
3532     // The remaining modifications are only necessary for HTTP and HTTPS.
3533     if (!request.url().isEmpty() && !request.url().protocolInHTTPFamily())
3534         return;
3535
3536     applyUserAgent(request);
3537     
3538     if (loadType == FrameLoadTypeReload) {
3539         request.setCachePolicy(ReloadIgnoringCacheData);
3540         request.setHTTPHeaderField("Cache-Control", "max-age=0");
3541     } else if (loadType == FrameLoadTypeReloadFromOrigin) {
3542         request.setCachePolicy(ReloadIgnoringCacheData);
3543         request.setHTTPHeaderField("Cache-Control", "no-cache");
3544         request.setHTTPHeaderField("Pragma", "no-cache");
3545     }
3546     
3547     if (mainResource)
3548         request.setHTTPAccept("application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5");
3549
3550     // Make sure we send the Origin header.
3551     addHTTPOriginIfNeeded(request, String());
3552
3553     // Always try UTF-8. If that fails, try frame encoding (if any) and then the default.
3554     // For a newly opened frame with an empty URL, encoding() should not be used, because this methods asks decoder, which uses ISO-8859-1.
3555     Settings* settings = m_frame->settings();
3556     request.setResponseContentDispositionEncodingFallbackArray("UTF-8", m_URL.isEmpty() ? m_encoding : encoding(), settings ? settings->defaultTextEncodingName() : String());
3557 }
3558
3559 void FrameLoader::addHTTPOriginIfNeeded(ResourceRequest& request, String origin)
3560 {
3561     if (!request.httpOrigin().isEmpty())
3562         return;  // Request already has an Origin header.
3563
3564     // Don't send an Origin header for GET or HEAD to avoid privacy issues.
3565     // For example, if an intranet page has a hyperlink to an external web
3566     // site, we don't want to include the Origin of the request because it
3567     // will leak the internal host name. Similar privacy concerns have lead
3568     // to the widespread suppression of the Referer header at the network
3569     // layer.
3570     if (request.httpMethod() == "GET" || request.httpMethod() == "HEAD")
3571         return;
3572
3573     // For non-GET and non-HEAD methods, always send an Origin header so the
3574     // server knows we support this feature.
3575
3576     if (origin.isEmpty()) {
3577         // If we don't know what origin header to attach, we attach the value
3578         // for an empty origin.
3579         origin = SecurityOrigin::createEmpty()->toString();
3580     }
3581
3582     request.setHTTPOrigin(origin);
3583 }
3584
3585 void FrameLoader::committedLoad(DocumentLoader* loader, const char* data, int length)
3586 {
3587     if (ArchiveFactory::isArchiveMimeType(loader->response().mimeType()))
3588         return;
3589     m_client->committedLoad(loader, data, length);
3590 }
3591
3592 void FrameLoader::loadPostRequest(const ResourceRequest& inRequest, const String& referrer, const String& frameName, bool lockHistory, FrameLoadType loadType, Event* event, PassRefPtr<FormState> prpFormState)
3593 {
3594     RefPtr<FormState> formState = prpFormState;
3595
3596     // When posting, use the NSURLRequestReloadIgnoringCacheData load flag.
3597     // This prevents a potential bug which may cause a page with a form that uses itself
3598     // as an action to be returned from the cache without submitting.
3599
3600     // FIXME: Where's the code that implements what the comment above says?
3601
3602     // Previously when this method was reached, the original FrameLoadRequest had been deconstructed to build a 
3603     // bunch of parameters that would come in here and then be built back up to a ResourceRequest.  In case
3604     // any caller depends on the immutability of the original ResourceRequest, I'm rebuilding a ResourceRequest
3605     // from scratch as it did all along.
3606     const KURL& url = inRequest.url();
3607     RefPtr<FormData> formData = inRequest.httpBody();
3608     const String& contentType = inRequest.httpContentType();
3609     String origin = inRequest.httpOrigin();
3610
3611     ResourceRequest workingResourceRequest(url);    
3612
3613     if (!referrer.isEmpty())
3614         workingResourceRequest.setHTTPReferrer(referrer);
3615     workingResourceRequest.setHTTPOrigin(origin);
3616     workingResourceRequest.setHTTPMethod("POST");
3617     workingResourceRequest.setHTTPBody(formData);
3618     workingResourceRequest.setHTTPContentType(contentType);
3619     addExtraFieldsToRequest(workingResourceRequest, loadType, true, true);
3620
3621     NavigationAction action(url, loadType, true, event);
3622
3623     if (!frameName.isEmpty()) {
3624         if (Frame* targetFrame = findFrameForNavigation(frameName))
3625             targetFrame->loader()->loadWithNavigationAction(workingResourceRequest, action, lockHistory, loadType, formState.release());
3626         else
3627             checkNewWindowPolicy(action, workingResourceRequest, formState.release(), frameName);
3628     } else
3629         loadWithNavigationAction(workingResourceRequest, action, lockHistory, loadType, formState.release());    
3630 }
3631
3632 void FrameLoader::loadEmptyDocumentSynchronously()
3633 {
3634     ResourceRequest request(KURL(""));
3635     load(request, false);
3636 }
3637
3638 unsigned long FrameLoader::loadResourceSynchronously(const ResourceRequest& request, ResourceError& error, ResourceResponse& response, Vector<char>& data)
3639 {
3640     // Since this is a subresource, we can load any URL (we ignore the return value).
3641     // But we still want to know whether we should hide the referrer or not, so we call the canLoad method.
3642     String referrer = m_outgoingReferrer;
3643     if (shouldHideReferrer(request.url(), referrer))
3644         referrer = String();
3645     
3646     ResourceRequest initialRequest = request;
3647     initialRequest.setTimeoutInterval(10);
3648     
3649     if (initialRequest.isConditional())
3650         initialRequest.setCachePolicy(ReloadIgnoringCacheData);
3651     else
3652         initialRequest.setCachePolicy(documentLoader()->request().cachePolicy());
3653     
3654     if (!referrer.isEmpty())
3655         initialRequest.setHTTPReferrer(referrer);
3656     addHTTPOriginIfNeeded(initialRequest, outgoingOrigin());
3657
3658     if (Page* page = m_frame->page())
3659         initialRequest.setMainDocumentURL(page->mainFrame()->loader()->documentLoader()->request().url());
3660     initialRequest.setHTTPUserAgent(client()->userAgent(request.url()));
3661
3662     unsigned long identifier = 0;    
3663     ResourceRequest newRequest(initialRequest);
3664     requestFromDelegate(newRequest, identifier, error);
3665
3666     if (error.isNull()) {
3667         ASSERT(!newRequest.isNull());
3668         
3669 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
3670         ApplicationCacheResource* resource;
3671         if (documentLoader()->shouldLoadResourceFromApplicationCache(newRequest, resource)) {
3672             if (resource) {
3673                 response = resource->response();
3674                 data.append(resource->data()->data(), resource->data()->size());
3675             } else
3676                 error = cannotShowURLError(newRequest);
3677         } else {
3678 #endif
3679             ResourceHandle::loadResourceSynchronously(newRequest, error, response, data, m_frame);
3680
3681 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
3682             // If normal loading results in a redirect to a resource with another origin (indicative of a captive portal), or a 4xx or 5xx status code or equivalent,
3683             // or if there were network errors (but not if the user canceled the download), then instead get, from the cache, the resource of the fallback entry
3684             // corresponding to the matched namespace.
3685             if ((!error.isNull() && !error.isCancellation())
3686                  || response.httpStatusCode() / 100 == 4 || response.httpStatusCode() / 100 == 5
3687                  || !protocolHostAndPortAreEqual(newRequest.url(), response.url())) {
3688                 if (documentLoader()->getApplicationCacheFallbackResource(newRequest, resource)) {
3689                     response = resource->response();
3690                     data.clear();
3691                     data.append(resource->data()->data(), resource->data()->size());
3692                 }
3693             }
3694         }
3695 #endif
3696     }
3697     
3698     sendRemainingDelegateMessages(identifier, response, data.size(), error);
3699     return identifier;
3700 }
3701
3702 void FrameLoader::assignIdentifierToInitialRequest(unsigned long identifier, const ResourceRequest& clientRequest)
3703 {
3704     return dispatchAssignIdentifierToInitialRequest(identifier, activeDocumentLoader(), clientRequest);
3705 }
3706
3707 void FrameLoader::willSendRequest(ResourceLoader* loader, ResourceRequest& clientRequest, const ResourceResponse& redirectResponse)
3708 {
3709     applyUserAgent(clientRequest);
3710     dispatchWillSendRequest(loader->documentLoader(), loader->identifier(), clientRequest, redirectResponse);
3711 }
3712
3713 void FrameLoader::didReceiveResponse(ResourceLoader* loader, const ResourceResponse& r)
3714 {
3715     activeDocumentLoader()->addResponse(r);
3716     
3717     if (Page* page = m_frame->page())
3718         page->progress()->incrementProgress(loader->identifier(), r);
3719     dispatchDidReceiveResponse(loader->documentLoader(), loader->identifier(), r);
3720 }
3721
3722 void FrameLoader::didReceiveData(ResourceLoader* loader, const char* data, int length, int lengthReceived)
3723 {
3724     if (Page* page = m_frame->page())
3725         page->progress()->incrementProgress(loader->identifier(), data, length);
3726     dispatchDidReceiveContentLength(loader->documentLoader(), loader->identifier(), lengthReceived);
3727 }
3728
3729 void FrameLoader::didFailToLoad(ResourceLoader* loader, const ResourceError& error)
3730 {
3731     if (Page* page = m_frame->page())
3732         page->progress()->completeProgress(loader->identifier());
3733     if (!error.isNull())
3734         m_client->dispatchDidFailLoading(loader->documentLoader(), loader->identifier(), error);
3735 }
3736
3737 const ResourceRequest& FrameLoader::originalRequest() const
3738 {
3739     return activeDocumentLoader()->originalRequestCopy();
3740 }
3741
3742 void FrameLoader::receivedMainResourceError(const ResourceError& error, bool isComplete)
3743 {
3744     // Retain because the stop may release the last reference to it.
3745     RefPtr<Frame> protect(m_frame);
3746
3747     RefPtr<DocumentLoader> loader = activeDocumentLoader();
3748     
3749     if (isComplete) {
3750         // FIXME: Don't want to do this if an entirely new load is going, so should check
3751         // that both data sources on the frame are either this or nil.
3752         stop();
3753         if (m_client->shouldFallBack(error))
3754             handleFallbackContent();
3755     }
3756     
3757     if (m_state == FrameStateProvisional && m_provisionalDocumentLoader) {
3758         KURL failedURL = m_provisionalDocumentLoader->originalRequestCopy().url();
3759         didNotOpenURL(failedURL);
3760             
3761         // We might have made a page cache item, but now we're bailing out due to an error before we ever
3762         // transitioned to the new page (before WebFrameState == commit).  The goal here is to restore any state
3763         // so that the existing view (that wenever got far enough to replace) can continue being used.
3764         invalidateCurrentItemCachedPage();
3765         
3766         // Call clientRedirectCancelledOrFinished here so that the frame load delegate is notified that the redirect's
3767         // status has changed, if there was a redirect. The frame load delegate may have saved some state about
3768         // the redirect in its -webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:. Since we are definitely
3769         // not going to use this provisional resource, as it was cancelled, notify the frame load delegate that the redirect
3770         // has ended.
3771         if (m_sentRedirectNotification)
3772             clientRedirectCancelledOrFinished(false);
3773     }
3774     
3775     
3776     loader->mainReceivedError(error, isComplete);
3777 }
3778
3779 void FrameLoader::callContinueFragmentScrollAfterNavigationPolicy(void* argument,
3780     const ResourceRequest& request, PassRefPtr<FormState>, bool shouldContinue)
3781 {
3782     FrameLoader* loader = static_cast<FrameLoader*>(argument);
3783     loader->continueFragmentScrollAfterNavigationPolicy(request, shouldContinue);
3784 }
3785
3786 void FrameLoader::continueFragmentScrollAfterNavigationPolicy(const ResourceRequest& request, bool shouldContinue)
3787 {
3788     bool isRedirect = m_quickRedirectComing || m_policyLoadType == FrameLoadTypeRedirectWithLockedBackForwardList;
3789     m_quickRedirectComing = false;
3790
3791     if (!shouldContinue)
3792         return;
3793
3794     KURL url = request.url();
3795     
3796     m_documentLoader->replaceRequestURLForAnchorScroll(url);
3797     if (!isRedirect && !shouldTreatURLAsSameAsCurrent(url)) {
3798         // NB: must happen after _setURL, since we add based on the current request.
3799         // Must also happen before we openURL and displace the scroll position, since
3800         // adding the BF item will save away scroll state.
3801         
3802         // NB2:  If we were loading a long, slow doc, and the user anchor nav'ed before
3803         // it was done, currItem is now set the that slow doc, and prevItem is whatever was
3804         // before it.  Adding the b/f item will bump the slow doc down to prevItem, even
3805         // though its load is not yet done.  I think this all works out OK, for one because
3806         // we have already saved away the scroll and doc state for the long slow load,
3807         // but it's not an obvious case.
3808
3809         addHistoryItemForFragmentScroll();
3810     }
3811     
3812     scrollToAnchor(url);
3813     
3814     if (!isRedirect)
3815         // This will clear previousItem from the rest of the frame tree that didn't
3816         // doing any loading. We need to make a pass on this now, since for anchor nav
3817         // we'll not go through a real load and reach Completed state.
3818         checkLoadComplete();
3819  
3820     m_client->dispatchDidChangeLocationWithinPage();
3821     m_client->didFinishLoad();
3822 }
3823
3824 bool FrameLoader::shouldScrollToAnchor(bool isFormSubmission, FrameLoadType loadType, const KURL& url)
3825 {
3826     // Should we do anchor navigation within the existing content?
3827
3828     // We don't do this if we are submitting a form, explicitly reloading,
3829     // currently displaying a frameset, or if the URL does not have a fragment.
3830     // These rules were originally based on what KHTML was doing in KHTMLPart::openURL.
3831
3832     // FIXME: What about load types other than Standard and Reload?
3833
3834     return !isFormSubmission
3835         && loadType != FrameLoadTypeReload
3836         && loadType != FrameLoadTypeReloadFromOrigin
3837         && loadType != FrameLoadTypeSame
3838         && !shouldReload(this->url(), url)
3839         // We don't want to just scroll if a link from within a
3840         // frameset is trying to reload the frameset into _top.
3841         && !m_frame->document()->isFrameSet();
3842 }
3843
3844 void FrameLoader::checkNewWindowPolicy(const NavigationAction& action, const ResourceRequest& request,
3845     PassRefPtr<FormState> formState, const String& frameName)
3846 {
3847     m_policyCheck.set(request, formState, frameName,
3848         callContinueLoadAfterNewWindowPolicy, this);
3849     m_client->dispatchDecidePolicyForNewWindowAction(&FrameLoader::continueAfterNewWindowPolicy,
3850         action, request, formState, frameName);
3851 }
3852
3853 void FrameLoader::continueAfterNewWindowPolicy(PolicyAction policy)
3854 {
3855     PolicyCheck check = m_policyCheck;
3856     m_policyCheck.clear();
3857
3858     switch (policy) {
3859         case PolicyIgnore:
3860             check.clearRequest();
3861             break;
3862         case PolicyDownload:
3863             m_client->startDownload(check.request());
3864             check.clearRequest();
3865             break;
3866         case PolicyUse:
3867             break;
3868     }
3869
3870     check.call(policy == PolicyUse);
3871 }
3872
3873 void FrameLoader::checkNavigationPolicy(const ResourceRequest& request, DocumentLoader* loader,
3874     PassRefPtr<FormState> formState, NavigationPolicyDecisionFunction function, void* argument)
3875 {
3876     NavigationAction action = loader->triggeringAction();
3877     if (action.isEmpty()) {
3878         action = NavigationAction(request.url(), NavigationTypeOther);
3879         loader->setTriggeringAction(action);
3880     }
3881         
3882     // Don't ask more than once for the same request or if we are loading an empty URL.
3883     // This avoids confusion on the part of the client.
3884     if (equalIgnoringHeaderFields(request, loader->lastCheckedRequest()) || (!request.isNull() && request.url().isEmpty())) {
3885         function(argument, request, 0, true);
3886         loader->setLastCheckedRequest(request);
3887         return;
3888     }
3889     
3890     // We are always willing to show alternate content for unreachable URLs;
3891     // treat it like a reload so it maintains the right state for b/f list.
3892     if (loader->substituteData().isValid() && !loader->substituteData().failingURL().isEmpty()) {
3893         if (isBackForwardLoadType(m_policyLoadType))
3894             m_policyLoadType = FrameLoadTypeReload;
3895         function(argument, request, 0, true);
3896         return;
3897     }
3898     
3899     loader->setLastCheckedRequest(request);
3900
3901     m_policyCheck.set(request, formState.get(), function, argument);
3902
3903     m_delegateIsDecidingNavigationPolicy = true;
3904     m_client->dispatchDecidePolicyForNavigationAction(&FrameLoader::continueAfterNavigationPolicy,
3905         action, request, formState);
3906     m_delegateIsDecidingNavigationPolicy = false;
3907 }
3908
3909 void FrameLoader::continueAfterNavigationPolicy(PolicyAction policy)
3910 {
3911     PolicyCheck check = m_policyCheck;
3912     m_policyCheck.clear();
3913
3914     bool shouldContinue = policy == PolicyUse;
3915     
3916     switch (policy) {
3917         case PolicyIgnore:
3918             check.clearRequest();
3919             break;
3920         case PolicyDownload:
3921             m_client->startDownload(check.request());
3922             check.clearRequest();
3923             break;
3924         case PolicyUse: {
3925             ResourceRequest request(check.request());
3926             
3927             if (!m_client->canHandleRequest(request)) {
3928                 handleUnimplementablePolicy(m_client->cannotShowURLError(check.request()));
3929                 check.clearRequest();
3930                 shouldContinue = false;
3931             }
3932             break;
3933         }
3934     }
3935
3936     check.call(shouldContinue);
3937 }
3938
3939 void FrameLoader::callContinueLoadAfterNavigationPolicy(void* argument,
3940     const ResourceRequest& request, PassRefPtr<FormState> formState, bool shouldContinue)
3941 {
3942     FrameLoader* loader = static_cast<FrameLoader*>(argument);
3943     loader->continueLoadAfterNavigationPolicy(request, formState, shouldContinue);
3944 }
3945
3946 void FrameLoader::continueLoadAfterNavigationPolicy(const ResourceRequest&, PassRefPtr<FormState> formState, bool shouldContinue)
3947 {
3948     // If we loaded an alternate page to replace an unreachableURL, we'll get in here with a
3949     // nil policyDataSource because loading the alternate page will have passed
3950     // through this method already, nested; otherwise, policyDataSource should still be set.
3951     ASSERT(m_policyDocumentLoader || !m_provisionalDocumentLoader->unreachableURL().isEmpty());
3952
3953     bool isTargetItem = m_provisionalHistoryItem ? m_provisionalHistoryItem->isTargetItem() : false;
3954
3955     // Two reasons we can't continue:
3956     //    1) Navigation policy delegate said we can't so request is nil. A primary case of this 
3957     //       is the user responding Cancel to the form repost nag sheet.
3958     //    2) User responded Cancel to an alert popped up by the before unload event handler.
3959     // The "before unload" event handler runs only for the main frame.
3960     bool canContinue = shouldContinue && (!isLoadingMainFrame() || m_frame->shouldClose());
3961
3962     if (!canContinue) {
3963         // If we were waiting for a quick redirect, but the policy delegate decided to ignore it, then we 
3964         // need to report that the client redirect was cancelled.
3965         if (m_quickRedirectComing)
3966             clientRedirectCancelledOrFinished(false);
3967
3968         setPolicyDocumentLoader(0);
3969
3970         // If the navigation request came from the back/forward menu, and we punt on it, we have the 
3971         // problem that we have optimistically moved the b/f cursor already, so move it back.  For sanity, 
3972         // we only do this when punting a navigation for the target frame or top-level frame.  
3973         if ((isTargetItem || isLoadingMainFrame()) && isBackForwardLoadType(m_policyLoadType))
3974             if (Page* page = m_frame->page()) {
3975                 Frame* mainFrame = page->mainFrame();
3976                 if (HistoryItem* resetItem = mainFrame->loader()->m_currentHistoryItem.get()) {
3977                     page->backForwardList()->goToItem(resetItem);
3978                     Settings* settings = m_frame->settings();
3979                     page->setGlobalHistoryItem((!settings || settings->privateBrowsingEnabled()) ? 0 : resetItem);
3980                 }
3981             }
3982         return;
3983     }
3984
3985     FrameLoadType type = m_policyLoadType;
3986     stopAllLoaders();
3987     
3988     // <rdar://problem/6250856> - In certain circumstances on pages with multiple frames, stopAllLoaders()
3989     // might detach the current FrameLoader, in which case we should bail on this newly defunct load. 
3990     if (!m_frame->page())
3991         return;
3992         
3993     setProvisionalDocumentLoader(m_policyDocumentLoader.get());
3994     m_loadType = type;
3995     setState(FrameStateProvisional);
3996
3997     setPolicyDocumentLoader(0);
3998
3999     if (isBackForwardLoadType(type) && loadProvisionalItemFromCachedPage())
4000         return;
4001
4002     if (formState)
4003         m_client->dispatchWillSubmitForm(&FrameLoader::continueLoadAfterWillSubmitForm, formState);
4004     else
4005         continueLoadAfterWillSubmitForm();
4006 }
4007
4008
4009 void FrameLoader::callContinueLoadAfterNewWindowPolicy(void* argument,
4010     const ResourceRequest& request, PassRefPtr<FormState> formState, const String& frameName, bool shouldContinue)
4011 {
4012     FrameLoader* loader = static_cast<FrameLoader*>(argument);
4013     loader->continueLoadAfterNewWindowPolicy(request, formState, frameName, shouldContinue);
4014 }
4015
4016 void FrameLoader::continueLoadAfterNewWindowPolicy(const ResourceRequest& request,
4017     PassRefPtr<FormState> formState, const String& frameName, bool shouldContinue)
4018 {
4019     if (!shouldContinue)
4020         return;
4021
4022     RefPtr<Frame> frame = m_frame;
4023     RefPtr<Frame> mainFrame = m_client->dispatchCreatePage();
4024     if (!mainFrame)
4025         return;
4026
4027     if (frameName != "_blank")
4028         mainFrame->tree()->setName(frameName);
4029
4030     mainFrame->loader()->setOpenedByDOM();
4031     mainFrame->loader()->m_client->dispatchShow();
4032     mainFrame->loader()->setOpener(frame.get());
4033     mainFrame->loader()->loadWithNavigationAction(request, NavigationAction(), false, FrameLoadTypeStandard, formState);
4034 }
4035
4036 void FrameLoader::sendRemainingDelegateMessages(unsigned long identifier, const ResourceResponse& response, int length, const ResourceError& error)
4037 {    
4038     if (!response.isNull())
4039         dispatchDidReceiveResponse(m_documentLoader.get(), identifier, response);
4040     
4041     if (length > 0)
4042         dispatchDidReceiveContentLength(m_documentLoader.get(), identifier, length);
4043     
4044     if (error.isNull())
4045         dispatchDidFinishLoading(m_documentLoader.get(), identifier);
4046     else
4047         m_client->dispatchDidFailLoading(m_documentLoader.get(), identifier, error);
4048 }
4049
4050 void FrameLoader::requestFromDelegate(ResourceRequest& request, unsigned long& identifier, ResourceError& error)
4051 {
4052     ASSERT(!request.isNull());
4053
4054     identifier = 0;
4055     if (Page* page = m_frame->page()) {
4056         identifier = page->progress()->createUniqueIdentifier();
4057         dispatchAssignIdentifierToInitialRequest(identifier, m_documentLoader.get(), request);
4058     }
4059
4060     ResourceRequest newRequest(request);
4061     dispatchWillSendRequest(m_documentLoader.get(), identifier, newRequest, ResourceResponse());
4062
4063     if (newRequest.isNull())
4064         error = cancelledError(request);
4065     else
4066         error = ResourceError();
4067
4068     request = newRequest;
4069 }
4070
4071 void FrameLoader::loadedResourceFromMemoryCache(const CachedResource* resource)
4072 {
4073     Page* page = m_frame->page();
4074     if (!page)
4075         return;
4076
4077     page->inspectorController()->didLoadResourceFromMemoryCache(m_documentLoader.get(), resource);
4078
4079     if (!resource->sendResourceLoadCallbacks() || m_documentLoader->haveToldClientAboutLoad(resource->url()))
4080         return;
4081
4082     if (!page->areMemoryCacheClientCallsEnabled()) {
4083         m_documentLoader->recordMemoryCacheLoadForFutureClientNotification(resource->url());
4084         m_documentLoader->didTellClientAboutLoad(resource->url());
4085         return;
4086     }
4087
4088     ResourceRequest request(resource->url());
4089     if (m_client->dispatchDidLoadResourceFromMemoryCache(m_documentLoader.get(), request, resource->response(), resource->encodedSize())) {
4090         m_documentLoader->didTellClientAboutLoad(resource->url());
4091         return;
4092     }
4093
4094     unsigned long identifier;
4095     ResourceError error;
4096     requestFromDelegate(request, identifier, error);
4097     sendRemainingDelegateMessages(identifier, resource->response(), resource->encodedSize(), error);
4098 }
4099
4100 void FrameLoader::applyUserAgent(ResourceRequest& request)
4101 {
4102     String userAgent = client()->userAgent(request.url());
4103     ASSERT(!userAgent.isNull());
4104     request.setHTTPUserAgent(userAgent);
4105 }
4106
4107 bool FrameLoader::canGoBackOrForward(int distance) const
4108 {
4109     if (Page* page = m_frame->page()) {
4110         if (distance == 0)
4111             return true;
4112         if (distance > 0 && distance <= page->backForwardList()->forwardListCount())
4113             return true;
4114         if (distance < 0 && -distance <= page->backForwardList()->backListCount())
4115             return true;
4116     }
4117     return false;
4118 }
4119
4120 int FrameLoader::getHistoryLength()
4121 {
4122     if (Page* page = m_frame->page())
4123         return page->backForwardList()->backListCount() + 1;
4124     return 0;
4125 }
4126
4127 KURL FrameLoader::historyURL(int distance)
4128 {
4129     if (Page* page = m_frame->page()) {
4130         BackForwardList* list = page->backForwardList();
4131         HistoryItem* item = list->itemAtIndex(distance);
4132         if (!item) {
4133             if (distance > 0) {
4134                 int forwardListCount = list->forwardListCount();
4135                 if (forwardListCount > 0)
4136                     item = list->itemAtIndex(forwardListCount);
4137             } else {
4138                 int backListCount = list->backListCount();
4139                 if (backListCount > 0)
4140                     item = list->itemAtIndex(-backListCount);
4141             }
4142         }
4143         if (item)
4144             return item->url();
4145     }
4146     return KURL();
4147 }
4148
4149 void FrameLoader::addHistoryItemForFragmentScroll()
4150 {
4151     addBackForwardItemClippedAtTarget(false);
4152 }
4153
4154 bool FrameLoader::loadProvisionalItemFromCachedPage()
4155 {
4156     RefPtr<CachedPage> cachedPage = pageCache()->get(m_provisionalHistoryItem.get());
4157     if (!cachedPage || !cachedPage->document())
4158         return false;
4159     provisionalDocumentLoader()->loadFromCachedPage(cachedPage.release());
4160     return true;
4161 }
4162
4163 void FrameLoader::cachePageForHistoryItem(HistoryItem* item)
4164 {
4165     if (!canCachePage() || item->isInPageCache())
4166         return;
4167
4168     if (Page* page = m_frame->page()) {
4169         RefPtr<CachedPage> cachedPage = CachedPage::create(page);
4170         pageCache()->add(item, cachedPage.release());
4171     }
4172 }
4173
4174 bool FrameLoader::shouldTreatURLAsSameAsCurrent(const KURL& url) const
4175 {
4176     if (!m_currentHistoryItem)
4177         return false;
4178     return url == m_currentHistoryItem->url() || url == m_currentHistoryItem->originalURL();
4179 }
4180
4181 PassRefPtr<HistoryItem> FrameLoader::createHistoryItem(bool useOriginal)
4182 {
4183     DocumentLoader* docLoader = documentLoader();
4184     
4185     KURL unreachableURL = docLoader ? docLoader->unreachableURL() : KURL();
4186     
4187     KURL url;
4188     KURL originalURL;
4189
4190     if (!unreachableURL.isEmpty()) {
4191         url = unreachableURL;
4192         originalURL = unreachableURL;
4193     } else {
4194         originalURL = docLoader ? docLoader->originalURL() : KURL();
4195         if (useOriginal)
4196             url = originalURL;
4197         else if (docLoader)
4198             url = docLoader->requestURL();
4199     }
4200
4201     LOG(History, "WebCoreHistory: Creating item for %s", url.string().ascii().data());
4202     
4203     // Frames that have never successfully loaded any content
4204     // may have no URL at all. Currently our history code can't
4205     // deal with such things, so we nip that in the bud here.
4206     // Later we may want to learn to live with nil for URL.
4207     // See bug 3368236 and related bugs for more information.
4208     if (url.isEmpty()) 
4209         url = blankURL();
4210     if (originalURL.isEmpty())
4211         originalURL = blankURL();
4212     
4213     Frame* parentFrame = m_frame->tree()->parent();
4214     String parent = parentFrame ? parentFrame->tree()->name() : "";
4215     String title = docLoader ? docLoader->title() : "";
4216
4217     RefPtr<HistoryItem> item = HistoryItem::create(url, m_frame->tree()->name(), parent, title);
4218     item->setOriginalURLString(originalURL.string());
4219
4220     if (!unreachableURL.isEmpty() || !docLoader || docLoader->response().httpStatusCode() >= 400)