eb28102dce425724f0a773004bd0859626d975fd
[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     // Any frame that hasn't completed yet?
1217     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
1218         if (!child->loader()->m_isComplete)
1219             return;
1220
1221     // Have we completed before?
1222     if (m_isComplete)
1223         return;
1224
1225     // Are we still parsing?
1226     if (m_frame->document()->parsing())
1227         return;
1228
1229     // Still waiting for images/scripts?
1230     if (numRequests(m_frame->document()))
1231         return;
1232
1233     // OK, completed.
1234     m_isComplete = true;
1235
1236     RefPtr<Frame> protect(m_frame);
1237     checkCallImplicitClose(); // if we didn't do it before
1238
1239     // Do not start a redirection timer for subframes here.
1240     // That is deferred until the parent is completed.
1241     if (m_scheduledRedirection && !m_frame->tree()->parent())
1242         startRedirectionTimer();
1243
1244     completed();
1245     if (m_frame->page())
1246         checkLoadComplete();
1247 }
1248
1249 void FrameLoader::checkCompletedTimerFired(Timer<FrameLoader>*)
1250 {
1251     checkCompleted();
1252 }
1253
1254 void FrameLoader::scheduleCheckCompleted()
1255 {
1256     if (!m_checkCompletedTimer.isActive())
1257         m_checkCompletedTimer.startOneShot(0);
1258 }
1259
1260 void FrameLoader::checkLoadCompleteTimerFired(Timer<FrameLoader>*)
1261 {
1262     if (!m_frame->page())
1263         return;
1264     checkLoadComplete();
1265 }
1266
1267 void FrameLoader::scheduleCheckLoadComplete()
1268 {
1269     if (!m_checkLoadCompleteTimer.isActive())
1270         m_checkLoadCompleteTimer.startOneShot(0);
1271 }
1272
1273 void FrameLoader::checkCallImplicitClose()
1274 {
1275     if (m_didCallImplicitClose || m_frame->document()->parsing())
1276         return;
1277
1278     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
1279         if (!child->loader()->m_isComplete) // still got a frame running -> too early
1280             return;
1281
1282     m_didCallImplicitClose = true;
1283     m_wasUnloadEventEmitted = false;
1284     m_frame->document()->implicitClose();
1285 }
1286
1287 KURL FrameLoader::baseURL() const
1288 {
1289     ASSERT(m_frame->document());
1290     return m_frame->document()->baseURL();
1291 }
1292
1293 String FrameLoader::baseTarget() const
1294 {
1295     ASSERT(m_frame->document());
1296     return m_frame->document()->baseTarget();
1297 }
1298
1299 KURL FrameLoader::completeURL(const String& url)
1300 {
1301     ASSERT(m_frame->document());
1302     return m_frame->document()->completeURL(url);
1303 }
1304
1305 void FrameLoader::scheduleHTTPRedirection(double delay, const String& url)
1306 {
1307     if (delay < 0 || delay > INT_MAX / 1000)
1308         return;
1309         
1310     if (!m_frame->page())
1311         return;
1312
1313     // We want a new history item if the refresh timeout is > 1 second.
1314     if (!m_scheduledRedirection || delay <= m_scheduledRedirection->delay)
1315         scheduleRedirection(new ScheduledRedirection(delay, url, true, delay <= 1, false, false));
1316 }
1317
1318 void FrameLoader::scheduleLocationChange(const String& url, const String& referrer, bool lockHistory, bool lockBackForwardList, bool wasUserGesture)
1319 {
1320     if (!m_frame->page())
1321         return;
1322
1323     // If the URL we're going to navigate to is the same as the current one, except for the
1324     // fragment part, we don't need to schedule the location change.
1325     KURL parsedURL(url);
1326     if (parsedURL.hasRef() && equalIgnoringRef(m_URL, parsedURL)) {
1327         changeLocation(url, referrer, lockHistory, lockBackForwardList, wasUserGesture);
1328         return;
1329     }
1330
1331     // Handle a location change of a page with no document as a special case.
1332     // This may happen when a frame changes the location of another frame.
1333     bool duringLoad = !m_committedFirstRealDocumentLoad;
1334
1335     // If a redirect was scheduled during a load, then stop the current load.
1336     // Otherwise when the current load transitions from a provisional to a 
1337     // committed state, pending redirects may be cancelled. 
1338     if (duringLoad) {
1339         if (m_provisionalDocumentLoader)
1340             m_provisionalDocumentLoader->stopLoading();
1341         stopLoading(true);   
1342     }
1343
1344     ScheduledRedirection::Type type = duringLoad
1345         ? ScheduledRedirection::locationChangeDuringLoad : ScheduledRedirection::locationChange;
1346     scheduleRedirection(new ScheduledRedirection(type, url, referrer, lockHistory, lockBackForwardList, wasUserGesture, false));
1347 }
1348
1349 void FrameLoader::scheduleRefresh(bool wasUserGesture)
1350 {
1351     if (!m_frame->page())
1352         return;
1353
1354     ScheduledRedirection::Type type = ScheduledRedirection::locationChange;
1355     scheduleRedirection(new ScheduledRedirection(type, m_URL.string(), m_outgoingReferrer, true, true, wasUserGesture, true));
1356 }
1357
1358 bool FrameLoader::isLocationChange(const ScheduledRedirection& redirection)
1359 {
1360     switch (redirection.type) {
1361         case ScheduledRedirection::redirection:
1362             return false;
1363         case ScheduledRedirection::historyNavigation:
1364         case ScheduledRedirection::locationChange:
1365         case ScheduledRedirection::locationChangeDuringLoad:
1366             return true;
1367     }
1368     ASSERT_NOT_REACHED();
1369     return false;
1370 }
1371
1372 void FrameLoader::scheduleHistoryNavigation(int steps)
1373 {
1374     if (!m_frame->page())
1375         return;
1376
1377     // navigation will always be allowed in the 0 steps case, which is OK because that's supposed to force a reload.
1378     if (!canGoBackOrForward(steps)) {
1379         cancelRedirection();
1380         return;
1381     }
1382
1383     // 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
1384     // (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),
1385     // then we don't need to schedule the navigation.
1386     if (steps != 0) {
1387         KURL destination = historyURL(steps);
1388         // FIXME: This doesn't seem like a reliable way to tell whether or not the load will be a fragment load.
1389         if (equalIgnoringRef(m_URL, destination) && m_URL != destination) {
1390             goBackOrForward(steps);
1391             return;
1392         }
1393     }
1394     
1395     scheduleRedirection(new ScheduledRedirection(steps));
1396 }
1397
1398 void FrameLoader::goBackOrForward(int distance)
1399 {
1400     if (distance == 0)
1401         return;
1402         
1403     Page* page = m_frame->page();
1404     if (!page)
1405         return;
1406     BackForwardList* list = page->backForwardList();
1407     if (!list)
1408         return;
1409     
1410     HistoryItem* item = list->itemAtIndex(distance);
1411     if (!item) {
1412         if (distance > 0) {
1413             int forwardListCount = list->forwardListCount();
1414             if (forwardListCount > 0) 
1415                 item = list->itemAtIndex(forwardListCount);
1416         } else {
1417             int backListCount = list->backListCount();
1418             if (backListCount > 0)
1419                 item = list->itemAtIndex(-backListCount);
1420         }
1421     }
1422     
1423     ASSERT(item); // we should not reach this line with an empty back/forward list
1424     if (item)
1425         page->goToItem(item, FrameLoadTypeIndexedBackForward);
1426 }
1427
1428 void FrameLoader::redirectionTimerFired(Timer<FrameLoader>*)
1429 {
1430     ASSERT(m_frame->page());
1431
1432     OwnPtr<ScheduledRedirection> redirection(m_scheduledRedirection.release());
1433
1434     switch (redirection->type) {
1435         case ScheduledRedirection::redirection:
1436         case ScheduledRedirection::locationChange:
1437         case ScheduledRedirection::locationChangeDuringLoad:
1438             changeLocation(redirection->url, redirection->referrer,
1439                 redirection->lockHistory, redirection->lockBackForwardList, redirection->wasUserGesture, redirection->wasRefresh);
1440             return;
1441         case ScheduledRedirection::historyNavigation:
1442             if (redirection->historySteps == 0) {
1443                 // Special case for go(0) from a frame -> reload only the frame
1444                 urlSelected(m_URL, "", 0, redirection->lockHistory, redirection->lockBackForwardList, redirection->wasUserGesture);
1445                 return;
1446             }
1447             // go(i!=0) from a frame navigates into the history of the frame only,
1448             // in both IE and NS (but not in Mozilla). We can't easily do that.
1449             goBackOrForward(redirection->historySteps);
1450             return;
1451     }
1452
1453     ASSERT_NOT_REACHED();
1454 }
1455
1456 /*
1457     In the case of saving state about a page with frames, we store a tree of items that mirrors the frame tree.  
1458     The item that was the target of the user's navigation is designated as the "targetItem".  
1459     When this method is called with doClip=YES we're able to create the whole tree except for the target's children, 
1460     which will be loaded in the future.  That part of the tree will be filled out as the child loads are committed.
1461 */
1462 void FrameLoader::loadURLIntoChildFrame(const KURL& url, const String& referer, Frame* childFrame)
1463 {
1464     ASSERT(childFrame);
1465     HistoryItem* parentItem = currentHistoryItem();
1466     FrameLoadType loadType = this->loadType();
1467     FrameLoadType childLoadType = FrameLoadTypeRedirectWithLockedBackForwardList;
1468
1469     KURL workingURL = url;
1470     
1471     // If we're moving in the backforward list, we might want to replace the content
1472     // of this child frame with whatever was there at that point.
1473     if (parentItem && parentItem->children().size() && isBackForwardLoadType(loadType)) {
1474         HistoryItem* childItem = parentItem->childItemWithName(childFrame->tree()->name());
1475         if (childItem) {
1476             // Use the original URL to ensure we get all the side-effects, such as
1477             // onLoad handlers, of any redirects that happened. An example of where
1478             // this is needed is Radar 3213556.
1479             workingURL = KURL(childItem->originalURLString());
1480             childLoadType = loadType;
1481             childFrame->loader()->setProvisionalHistoryItem(childItem);
1482         }
1483     }
1484
1485     RefPtr<Archive> subframeArchive = activeDocumentLoader()->popArchiveForSubframe(childFrame->tree()->name());
1486     
1487     if (subframeArchive)
1488         childFrame->loader()->loadArchive(subframeArchive.release());
1489     else
1490         childFrame->loader()->loadURL(workingURL, referer, String(), false, childLoadType, 0, 0);
1491 }
1492
1493 void FrameLoader::loadArchive(PassRefPtr<Archive> prpArchive)
1494 {
1495     RefPtr<Archive> archive = prpArchive;
1496     
1497     ArchiveResource* mainResource = archive->mainResource();
1498     ASSERT(mainResource);
1499     if (!mainResource)
1500         return;
1501         
1502     SubstituteData substituteData(mainResource->data(), mainResource->mimeType(), mainResource->textEncoding(), KURL());
1503     
1504     ResourceRequest request(mainResource->url());
1505 #if PLATFORM(MAC)
1506     request.applyWebArchiveHackForMail();
1507 #endif
1508
1509     RefPtr<DocumentLoader> documentLoader = m_client->createDocumentLoader(request, substituteData);
1510     documentLoader->addAllArchiveResources(archive.get());
1511     load(documentLoader.get());
1512 }
1513
1514 String FrameLoader::encoding() const
1515 {
1516     if (m_encodingWasChosenByUser && !m_encoding.isEmpty())
1517         return m_encoding;
1518     if (m_decoder && m_decoder->encoding().isValid())
1519         return m_decoder->encoding().name();
1520     Settings* settings = m_frame->settings();
1521     return settings ? settings->defaultTextEncodingName() : String();
1522 }
1523
1524 bool FrameLoader::gotoAnchor(const String& name)
1525 {
1526     ASSERT(m_frame->document());
1527
1528     if (!m_frame->document()->haveStylesheetsLoaded()) {
1529         m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(true);
1530         return false;
1531     }
1532
1533     m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(false);
1534
1535     Element* anchorNode = m_frame->document()->findAnchor(name);
1536
1537 #if ENABLE(SVG)
1538     if (m_frame->document()->isSVGDocument()) {
1539         if (name.startsWith("xpointer(")) {
1540             // We need to parse the xpointer reference here
1541         } else if (name.startsWith("svgView(")) {
1542             RefPtr<SVGSVGElement> svg = static_cast<SVGDocument*>(m_frame->document())->rootElement();
1543             if (!svg->currentView()->parseViewSpec(name))
1544                 return false;
1545             svg->setUseCurrentView(true);
1546         } else {
1547             if (anchorNode && anchorNode->hasTagName(SVGNames::viewTag)) {
1548                 RefPtr<SVGViewElement> viewElement = anchorNode->hasTagName(SVGNames::viewTag) ? static_cast<SVGViewElement*>(anchorNode) : 0;
1549                 if (viewElement.get()) {
1550                     RefPtr<SVGSVGElement> svg = static_cast<SVGSVGElement*>(SVGLocatable::nearestViewportElement(viewElement.get()));
1551                     svg->inheritViewAttributes(viewElement.get());
1552                 }
1553             }
1554         }
1555         // FIXME: need to decide which <svg> to focus on, and zoom to that one
1556         // FIXME: need to actually "highlight" the viewTarget(s)
1557     }
1558 #endif
1559
1560     m_frame->document()->setCSSTarget(anchorNode); // Setting to null will clear the current target.
1561   
1562     // Implement the rule that "" and "top" both mean top of page as in other browsers.
1563     if (!anchorNode && !(name.isEmpty() || equalIgnoringCase(name, "top")))
1564         return false;
1565
1566     // We need to update the layout before scrolling, otherwise we could
1567     // really mess things up if an anchor scroll comes at a bad moment.
1568     m_frame->document()->updateRendering();
1569     // Only do a layout if changes have occurred that make it necessary.
1570     if (m_frame->view() && m_frame->contentRenderer() && m_frame->contentRenderer()->needsLayout())
1571         m_frame->view()->layout();
1572   
1573     // Scroll nested layers and frames to reveal the anchor.
1574     // Align to the top and to the closest side (this matches other browsers).
1575     RenderObject* renderer;
1576     IntRect rect;
1577     if (!anchorNode)
1578         renderer = m_frame->document()->renderer(); // top of document
1579     else {
1580         renderer = anchorNode->renderer();
1581         rect = anchorNode->getRect();
1582     }
1583     if (renderer)
1584         renderer->enclosingLayer()->scrollRectToVisible(rect, true, RenderLayer::gAlignToEdgeIfNeeded, RenderLayer::gAlignTopAlways);
1585
1586     return true;
1587 }
1588
1589 bool FrameLoader::requestObject(RenderPart* renderer, const String& url, const AtomicString& frameName,
1590     const String& mimeType, const Vector<String>& paramNames, const Vector<String>& paramValues)
1591 {
1592     if (url.isEmpty() && mimeType.isEmpty())
1593         return false;
1594
1595     KURL completedURL;
1596     if (!url.isEmpty())
1597         completedURL = completeURL(url);
1598
1599     bool useFallback;
1600     if (shouldUsePlugin(completedURL, mimeType, renderer->hasFallbackContent(), useFallback)) {
1601         Settings* settings = m_frame->settings();
1602         if (!settings || !settings->arePluginsEnabled() || 
1603             (!settings->isJavaEnabled() && MIMETypeRegistry::isJavaAppletMIMEType(mimeType)))
1604             return false;
1605         return loadPlugin(renderer, completedURL, mimeType, paramNames, paramValues, useFallback);
1606     }
1607
1608     ASSERT(renderer->node()->hasTagName(objectTag) || renderer->node()->hasTagName(embedTag));
1609     HTMLPlugInElement* element = static_cast<HTMLPlugInElement*>(renderer->node());
1610     
1611     // FIXME: OK to always make a new frame? When does the old frame get removed?
1612     return loadSubframe(element, completedURL, frameName, m_outgoingReferrer);
1613 }
1614
1615 bool FrameLoader::shouldUsePlugin(const KURL& url, const String& mimeType, bool hasFallback, bool& useFallback)
1616 {
1617     if (m_client->shouldUsePluginDocument(mimeType)) {
1618         useFallback = false;
1619         return true;
1620     }
1621
1622     // Allow other plug-ins to win over QuickTime because if the user has installed a plug-in that
1623     // can handle TIFF (which QuickTime can also handle) they probably intended to override QT.
1624     if (m_frame->page() && (mimeType == "image/tiff" || mimeType == "image/tif" || mimeType == "image/x-tiff")) {
1625         const PluginData* pluginData = m_frame->page()->pluginData();
1626         String pluginName = pluginData ? pluginData->pluginNameForMimeType(mimeType) : String();
1627         if (!pluginName.isEmpty() && !pluginName.contains("QuickTime", false)) 
1628             return true;
1629     }
1630         
1631     ObjectContentType objectType = m_client->objectContentType(url, mimeType);
1632     // If an object's content can't be handled and it has no fallback, let
1633     // it be handled as a plugin to show the broken plugin icon.
1634     useFallback = objectType == ObjectContentNone && hasFallback;
1635     return objectType == ObjectContentNone || objectType == ObjectContentNetscapePlugin || objectType == ObjectContentOtherPlugin;
1636 }
1637
1638 static HTMLPlugInElement* toPlugInElement(Node* node)
1639 {
1640     if (!node)
1641         return 0;
1642
1643 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
1644     ASSERT(node->hasTagName(objectTag) || node->hasTagName(embedTag) 
1645         || node->hasTagName(videoTag) || node->hasTagName(audioTag)
1646         || node->hasTagName(appletTag));
1647 #else
1648     ASSERT(node->hasTagName(objectTag) || node->hasTagName(embedTag) 
1649         || node->hasTagName(appletTag));
1650 #endif
1651
1652     return static_cast<HTMLPlugInElement*>(node);
1653 }
1654     
1655 bool FrameLoader::loadPlugin(RenderPart* renderer, const KURL& url, const String& mimeType, 
1656     const Vector<String>& paramNames, const Vector<String>& paramValues, bool useFallback)
1657 {
1658     Widget* widget = 0;
1659
1660     if (renderer && !useFallback) {
1661         HTMLPlugInElement* element = toPlugInElement(renderer->node());
1662
1663         if (!canLoad(url, String(), frame()->document())) {
1664             FrameLoader::reportLocalLoadFailed(m_frame, url.string());
1665             return false;
1666         }
1667
1668         widget = m_client->createPlugin(IntSize(renderer->contentWidth(), renderer->contentHeight()), 
1669                                         element, url, paramNames, paramValues, mimeType,
1670                                         m_frame->document()->isPluginDocument());
1671         if (widget) {
1672             renderer->setWidget(widget);
1673             m_containsPlugIns = true;
1674         }
1675     }
1676
1677     return widget != 0;
1678 }
1679
1680 void FrameLoader::clearRecordedFormValues()
1681 {
1682     m_formAboutToBeSubmitted = 0;
1683     m_formValuesAboutToBeSubmitted.clear();
1684 }
1685
1686 void FrameLoader::setFormAboutToBeSubmitted(PassRefPtr<HTMLFormElement> element)
1687 {
1688     m_formAboutToBeSubmitted = element;
1689 }
1690
1691 void FrameLoader::recordFormValue(const String& name, const String& value)
1692 {
1693     m_formValuesAboutToBeSubmitted.set(name, value);
1694 }
1695
1696 void FrameLoader::parentCompleted()
1697 {
1698     if (m_scheduledRedirection && !m_redirectionTimer.isActive())
1699         startRedirectionTimer();
1700 }
1701
1702 String FrameLoader::outgoingReferrer() const
1703 {
1704     return m_outgoingReferrer;
1705 }
1706
1707 String FrameLoader::outgoingOrigin() const
1708 {
1709     return m_frame->document()->securityOrigin()->toString();
1710 }
1711
1712 Frame* FrameLoader::opener()
1713 {
1714     return m_opener;
1715 }
1716
1717 void FrameLoader::setOpener(Frame* opener)
1718 {
1719     if (m_opener)
1720         m_opener->loader()->m_openedFrames.remove(m_frame);
1721     if (opener)
1722         opener->loader()->m_openedFrames.add(m_frame);
1723     m_opener = opener;
1724
1725     if (m_frame->document()) {
1726         m_frame->document()->initSecurityContext();
1727         m_frame->domWindow()->setSecurityOrigin(m_frame->document()->securityOrigin());
1728     }
1729 }
1730
1731 bool FrameLoader::openedByDOM() const
1732 {
1733     return m_openedByDOM;
1734 }
1735
1736 void FrameLoader::setOpenedByDOM()
1737 {
1738     m_openedByDOM = true;
1739 }
1740
1741 void FrameLoader::handleFallbackContent()
1742 {
1743     HTMLFrameOwnerElement* owner = m_frame->ownerElement();
1744     if (!owner || !owner->hasTagName(objectTag))
1745         return;
1746     static_cast<HTMLObjectElement*>(owner)->renderFallbackContent();
1747 }
1748
1749 void FrameLoader::provisionalLoadStarted()
1750 {
1751     Page* page = m_frame->page();
1752     
1753     // this is used to update the current history item
1754     // in the event of a navigation aytime during loading
1755     m_navigationDuringLoad = false;
1756     if (page) {
1757         Document *document = page->mainFrame()->document();
1758         m_navigationDuringLoad = !page->mainFrame()->loader()->isComplete() || (document && document->processingLoadEvent());
1759     }
1760     
1761     m_firstLayoutDone = false;
1762     cancelRedirection(true);
1763     m_client->provisionalLoadStarted();
1764 }
1765
1766 bool FrameLoader::userGestureHint()
1767 {
1768     Frame* frame = m_frame->tree()->top();
1769     if (!frame->script()->isEnabled())
1770         return true; // If JavaScript is disabled, a user gesture must have initiated the navigation.
1771     return frame->script()->processingUserGesture(); // FIXME: Use pageIsProcessingUserGesture.
1772 }
1773
1774 void FrameLoader::didNotOpenURL(const KURL& url)
1775 {
1776     if (m_submittedFormURL == url)
1777         m_submittedFormURL = KURL();
1778 }
1779
1780 void FrameLoader::resetMultipleFormSubmissionProtection()
1781 {
1782     m_submittedFormURL = KURL();
1783 }
1784
1785 void FrameLoader::setEncoding(const String& name, bool userChosen)
1786 {
1787     if (!m_workingURL.isEmpty())
1788         receivedFirstData();
1789     m_encoding = name;
1790     m_encodingWasChosenByUser = userChosen;
1791 }
1792
1793 void FrameLoader::addData(const char* bytes, int length)
1794 {
1795     ASSERT(m_workingURL.isEmpty());
1796     ASSERT(m_frame->document());
1797     ASSERT(m_frame->document()->parsing());
1798     write(bytes, length);
1799 }
1800
1801 bool FrameLoader::canCachePageContainingThisFrame()
1802 {
1803     return m_documentLoader
1804         && m_documentLoader->mainDocumentError().isNull()
1805         && !m_frame->tree()->childCount()
1806         // FIXME: If we ever change this so that frames with plug-ins will be cached,
1807         // we need to make sure that we don't cache frames that have outstanding NPObjects
1808         // (objects created by the plug-in). Since there is no way to pause/resume a Netscape plug-in,
1809         // they would need to be destroyed and then recreated, and there is no way that we can recreate
1810         // the right NPObjects. See <rdar://problem/5197041> for more information.
1811         && !m_containsPlugIns
1812         && !m_URL.protocolIs("https")
1813         && !m_frame->document()->hasWindowEventListener(eventNames().unloadEvent)
1814 #if ENABLE(DATABASE)
1815         && !m_frame->document()->hasOpenDatabases()
1816 #endif
1817         && !m_frame->document()->usingGeolocation()
1818         && m_currentHistoryItem
1819         && !isQuickRedirectComing()
1820         && !m_documentLoader->isLoadingInAPISense()
1821         && !m_documentLoader->isStopping()
1822         && m_frame->document()->canSuspendActiveDOMObjects()
1823 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
1824         // FIXME: We should investigating caching frames that have an associated
1825         // application cache. <rdar://problem/5917899> tracks that work.
1826         && !m_documentLoader->applicationCache()
1827         && !m_documentLoader->candidateApplicationCacheGroup()
1828 #endif
1829         && m_client->canCachePage()
1830         ;
1831 }
1832
1833 bool FrameLoader::canCachePage()
1834 {
1835 #ifndef NDEBUG
1836     logCanCachePageDecision();
1837 #endif
1838     
1839     // Cache the page, if possible.
1840     // Don't write to the cache if in the middle of a redirect, since we will want to
1841     // store the final page we end up on.
1842     // No point writing to the cache on a reload or loadSame, since we will just write
1843     // over it again when we leave that page.
1844     // FIXME: <rdar://problem/4886592> - We should work out the complexities of caching pages with frames as they
1845     // are the most interesting pages on the web, and often those that would benefit the most from caching!
1846     FrameLoadType loadType = this->loadType();
1847     
1848     return !m_frame->tree()->parent()
1849         && canCachePageContainingThisFrame()
1850         && m_frame->page()
1851         && m_frame->page()->backForwardList()->enabled()
1852         && m_frame->page()->backForwardList()->capacity() > 0
1853         && m_frame->page()->settings()->usesPageCache()
1854         && loadType != FrameLoadTypeReload 
1855         && loadType != FrameLoadTypeReloadFromOrigin
1856         && loadType != FrameLoadTypeSame
1857         ;
1858 }
1859
1860 #ifndef NDEBUG
1861 static String& pageCacheLogPrefix(int indentLevel)
1862 {
1863     static int previousIndent = -1;
1864     DEFINE_STATIC_LOCAL(String, prefix, ());
1865     
1866     if (indentLevel != previousIndent) {    
1867         previousIndent = indentLevel;
1868         prefix.truncate(0);
1869         for (int i = 0; i < previousIndent; ++i)
1870             prefix += "    ";
1871     }
1872     
1873     return prefix;
1874 }
1875
1876 static void pageCacheLog(const String& prefix, const String& message)
1877 {
1878     LOG(PageCache, "%s%s", prefix.utf8().data(), message.utf8().data());
1879 }
1880
1881 #define PCLOG(...) pageCacheLog(pageCacheLogPrefix(indentLevel), String::format(__VA_ARGS__))
1882
1883 void FrameLoader::logCanCachePageDecision()
1884 {
1885     // Only bother logging for main frames that have actually loaded and have content.
1886     if (m_creatingInitialEmptyDocument)
1887         return;
1888     KURL currentURL = m_documentLoader ? m_documentLoader->url() : KURL();
1889     if (currentURL.isEmpty())
1890         return;
1891
1892     int indentLevel = 0;
1893     PCLOG("--------\n Determining if page can be cached:");
1894
1895     bool cannotCache = !logCanCacheFrameDecision(1);
1896         
1897     FrameLoadType loadType = this->loadType();
1898     do {
1899         if (m_frame->tree()->parent())
1900             { PCLOG("   -Frame has a parent frame"); cannotCache = true; }
1901         if (!m_frame->page()) {
1902             PCLOG("   -There is no Page object");
1903             cannotCache = true;
1904             break;
1905         }
1906         if (!m_frame->page()->backForwardList()->enabled())
1907             { PCLOG("   -The back/forward list is disabled"); cannotCache = true; }
1908         if (!(m_frame->page()->backForwardList()->capacity() > 0))
1909             { PCLOG("   -The back/forward list has a 0 capacity"); cannotCache = true; }
1910         if (!m_frame->page()->settings()->usesPageCache())
1911             { PCLOG("   -Page settings says b/f cache disabled"); cannotCache = true; }
1912         if (loadType == FrameLoadTypeReload)
1913             { PCLOG("   -Load type is: Reload"); cannotCache = true; }
1914         if (loadType == FrameLoadTypeReloadFromOrigin)
1915             { PCLOG("   -Load type is: Reload from origin"); cannotCache = true; }
1916         if (loadType == FrameLoadTypeSame)
1917             { PCLOG("   -Load type is: Same"); cannotCache = true; }
1918     } while (false);
1919     
1920     PCLOG(cannotCache ? " Page CANNOT be cached\n--------" : " Page CAN be cached\n--------");
1921 }
1922
1923 bool FrameLoader::logCanCacheFrameDecision(int indentLevel)
1924 {
1925     // Only bother logging for frames that have actually loaded and have content.
1926     if (m_creatingInitialEmptyDocument)
1927         return false;
1928     KURL currentURL = m_documentLoader ? m_documentLoader->url() : KURL();
1929     if (currentURL.isEmpty())
1930         return false;
1931
1932     PCLOG("+---");
1933     KURL newURL = m_provisionalDocumentLoader ? m_provisionalDocumentLoader->url() : KURL();
1934     if (!newURL.isEmpty())
1935         PCLOG(" Determining if frame can be cached navigating from (%s) to (%s):", currentURL.string().utf8().data(), newURL.string().utf8().data());
1936     else
1937         PCLOG(" Determining if subframe with URL (%s) can be cached:", currentURL.string().utf8().data());
1938         
1939     bool cannotCache = false;
1940
1941     do {
1942         if (!m_documentLoader) {
1943             PCLOG("   -There is no DocumentLoader object");
1944             cannotCache = true;
1945             break;
1946         }
1947         if (!m_documentLoader->mainDocumentError().isNull())
1948             { PCLOG("   -Main document has an error"); cannotCache = true; }
1949         if (m_frame->tree()->childCount())
1950             { PCLOG("   -Frame has child frames"); cannotCache = true; }
1951         if (m_containsPlugIns)
1952             { PCLOG("   -Frame contains plugins"); cannotCache = true; }
1953         if (m_URL.protocolIs("https"))
1954             { PCLOG("   -Frame is HTTPS"); cannotCache = true; }
1955         if (m_frame->document()->hasWindowEventListener(eventNames().unloadEvent))
1956             { PCLOG("   -Frame has an unload event listener"); cannotCache = true; }
1957 #if ENABLE(DATABASE)
1958         if (m_frame->document()->hasOpenDatabases())
1959             { PCLOG("   -Frame has open database handles"); cannotCache = true; }
1960 #endif
1961         if (m_frame->document()->usingGeolocation())
1962             { PCLOG("   -Frame uses Geolocation"); cannotCache = true; }
1963         if (!m_currentHistoryItem)
1964             { PCLOG("   -No current history item"); cannotCache = true; }
1965         if (isQuickRedirectComing())
1966             { PCLOG("   -Quick redirect is coming"); cannotCache = true; }
1967         if (m_documentLoader->isLoadingInAPISense())
1968             { PCLOG("   -DocumentLoader is still loading in API sense"); cannotCache = true; }
1969         if (m_documentLoader->isStopping())
1970             { PCLOG("   -DocumentLoader is in the middle of stopping"); cannotCache = true; }
1971         if (!m_frame->document()->canSuspendActiveDOMObjects())
1972             { PCLOG("   -The document cannot suspect its active DOM Objects"); cannotCache = true; }
1973 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
1974         if (m_documentLoader->applicationCache())
1975             { PCLOG("   -The DocumentLoader has an active application cache"); cannotCache = true; }
1976         if (m_documentLoader->candidateApplicationCacheGroup())
1977             { PCLOG("   -The DocumentLoader has a candidateApplicationCacheGroup"); cannotCache = true; }
1978 #endif
1979         if (!m_client->canCachePage())
1980             { PCLOG("   -The client says this frame cannot be cached"); cannotCache = true; }
1981     } while (false);
1982
1983     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
1984         if (!child->loader()->logCanCacheFrameDecision(indentLevel + 1))
1985             cannotCache = true;
1986     
1987     PCLOG(cannotCache ? " Frame CANNOT be cached" : " Frame CAN be cached");
1988     PCLOG("+---");
1989
1990     return !cannotCache;
1991 }
1992 #endif
1993
1994 void FrameLoader::updatePolicyBaseURL()
1995 {
1996     if (m_frame->tree()->parent())
1997         setPolicyBaseURL(m_frame->tree()->parent()->document()->policyBaseURL());
1998     else
1999         setPolicyBaseURL(m_URL);
2000 }
2001
2002 void FrameLoader::setPolicyBaseURL(const KURL& url)
2003 {
2004     m_frame->document()->setPolicyBaseURL(url);
2005     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
2006         child->loader()->setPolicyBaseURL(url);
2007 }
2008
2009 // This does the same kind of work that didOpenURL does, except it relies on the fact
2010 // that a higher level already checked that the URLs match and the scrolling is the right thing to do.
2011 void FrameLoader::scrollToAnchor(const KURL& url)
2012 {
2013     m_URL = url;
2014     updateHistoryForAnchorScroll();
2015
2016     // If we were in the autoscroll/panScroll mode we want to stop it before following the link to the anchor
2017     m_frame->eventHandler()->stopAutoscrollTimer();
2018     started();
2019     gotoAnchor();
2020
2021     // It's important to model this as a load that starts and immediately finishes.
2022     // Otherwise, the parent frame may think we never finished loading.
2023     m_isComplete = false;
2024     checkCompleted();
2025 }
2026
2027 bool FrameLoader::isComplete() const
2028 {
2029     return m_isComplete;
2030 }
2031
2032 void FrameLoader::scheduleRedirection(ScheduledRedirection* redirection)
2033 {
2034     ASSERT(m_frame->page());
2035
2036     stopRedirectionTimer();
2037     m_scheduledRedirection.set(redirection);
2038     if (!m_isComplete && redirection->type != ScheduledRedirection::redirection)
2039         completed();
2040     if (m_isComplete || redirection->type != ScheduledRedirection::redirection)
2041         startRedirectionTimer();
2042 }
2043
2044 void FrameLoader::startRedirectionTimer()
2045 {
2046     ASSERT(m_frame->page());
2047     ASSERT(m_scheduledRedirection);
2048
2049     m_redirectionTimer.stop();
2050     m_redirectionTimer.startOneShot(m_scheduledRedirection->delay);
2051
2052     switch (m_scheduledRedirection->type) {
2053         case ScheduledRedirection::redirection:
2054         case ScheduledRedirection::locationChange:
2055         case ScheduledRedirection::locationChangeDuringLoad:
2056             clientRedirected(KURL(m_scheduledRedirection->url),
2057                 m_scheduledRedirection->delay,
2058                 currentTime() + m_redirectionTimer.nextFireInterval(),
2059                 m_scheduledRedirection->lockBackForwardList,
2060                 m_isExecutingJavaScriptFormAction);
2061             return;
2062         case ScheduledRedirection::historyNavigation:
2063             // Don't report history navigations.
2064             return;
2065     }
2066     ASSERT_NOT_REACHED();
2067 }
2068
2069 void FrameLoader::stopRedirectionTimer()
2070 {
2071     if (!m_redirectionTimer.isActive())
2072         return;
2073
2074     m_redirectionTimer.stop();
2075
2076     if (m_scheduledRedirection) {
2077         switch (m_scheduledRedirection->type) {
2078             case ScheduledRedirection::redirection:
2079             case ScheduledRedirection::locationChange:
2080             case ScheduledRedirection::locationChangeDuringLoad:
2081                 clientRedirectCancelledOrFinished(m_cancellingWithLoadInProgress);
2082                 return;
2083             case ScheduledRedirection::historyNavigation:
2084                 // Don't report history navigations.
2085                 return;
2086         }
2087         ASSERT_NOT_REACHED();
2088     }
2089 }
2090
2091 void FrameLoader::completed()
2092 {
2093     RefPtr<Frame> protect(m_frame);
2094     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
2095         child->loader()->parentCompleted();
2096     if (Frame* parent = m_frame->tree()->parent())
2097         parent->loader()->checkCompleted();
2098     submitFormAgain();
2099 }
2100
2101 void FrameLoader::started()
2102 {
2103     for (Frame* frame = m_frame; frame; frame = frame->tree()->parent())
2104         frame->loader()->m_isComplete = false;
2105 }
2106
2107 bool FrameLoader::containsPlugins() const 
2108
2109     return m_containsPlugIns;
2110 }
2111
2112 void FrameLoader::prepareForLoadStart()
2113 {
2114     if (Page* page = m_frame->page())
2115         page->progress()->progressStarted(m_frame);
2116     m_client->dispatchDidStartProvisionalLoad();
2117 }
2118
2119 void FrameLoader::setupForReplace()
2120 {
2121     setState(FrameStateProvisional);
2122     m_provisionalDocumentLoader = m_documentLoader;
2123     m_documentLoader = 0;
2124     detachChildren();
2125 }
2126
2127 void FrameLoader::setupForReplaceByMIMEType(const String& newMIMEType)
2128 {
2129     activeDocumentLoader()->setupForReplaceByMIMEType(newMIMEType);
2130 }
2131
2132 void FrameLoader::loadFrameRequestWithFormAndValues(const FrameLoadRequest& request, bool lockHistory, bool lockBackForwardList, Event* event,
2133     HTMLFormElement* submitForm, const HashMap<String, String>& formValues)
2134 {
2135     RefPtr<FormState> formState;
2136     if (submitForm)
2137         formState = FormState::create(submitForm, formValues, m_frame);
2138     
2139     KURL url = request.resourceRequest().url();
2140
2141     String referrer;
2142     String argsReferrer = request.resourceRequest().httpReferrer();
2143     if (!argsReferrer.isEmpty())
2144         referrer = argsReferrer;
2145     else
2146         referrer = m_outgoingReferrer;
2147
2148     ASSERT(frame()->document());
2149     if (url.protocolIs("file")) {
2150         if (!canLoad(url, String(), frame()->document()) && !canLoad(url, referrer)) {
2151             FrameLoader::reportLocalLoadFailed(m_frame, url.string());
2152             return;
2153         }
2154     }
2155
2156     if (shouldHideReferrer(url, referrer))
2157         referrer = String();
2158     
2159     FrameLoadType loadType;
2160     if (request.resourceRequest().cachePolicy() == ReloadIgnoringCacheData)
2161         loadType = FrameLoadTypeReload;
2162     else if (lockBackForwardList)
2163         loadType = FrameLoadTypeRedirectWithLockedBackForwardList;
2164     else
2165         loadType = FrameLoadTypeStandard;
2166
2167     if (request.resourceRequest().httpMethod() == "POST")
2168         loadPostRequest(request.resourceRequest(), referrer, request.frameName(), lockHistory, loadType, event, formState.release());
2169     else
2170         loadURL(request.resourceRequest().url(), referrer, request.frameName(), lockHistory, loadType, event, formState.release());
2171
2172     Frame* targetFrame = findFrameForNavigation(request.frameName());
2173     if (targetFrame && targetFrame != m_frame)
2174         if (Page* page = targetFrame->page())
2175             page->chrome()->focus();
2176 }
2177
2178 void FrameLoader::loadURL(const KURL& newURL, const String& referrer, const String& frameName, bool lockHistory, FrameLoadType newLoadType,
2179     Event* event, PassRefPtr<FormState> prpFormState)
2180 {
2181     RefPtr<FormState> formState = prpFormState;
2182     bool isFormSubmission = formState;
2183     
2184     ResourceRequest request(newURL);
2185     if (!referrer.isEmpty()) {
2186         request.setHTTPReferrer(referrer);
2187         RefPtr<SecurityOrigin> referrerOrigin = SecurityOrigin::createFromString(referrer);
2188         addHTTPOriginIfNeeded(request, referrerOrigin->toString());
2189     }
2190     addExtraFieldsToRequest(request, newLoadType, true, event || isFormSubmission);
2191     if (newLoadType == FrameLoadTypeReload || newLoadType == FrameLoadTypeReloadFromOrigin)
2192         request.setCachePolicy(ReloadIgnoringCacheData);
2193
2194     ASSERT(newLoadType != FrameLoadTypeSame);
2195
2196     NavigationAction action(newURL, newLoadType, isFormSubmission, event);
2197
2198     if (!frameName.isEmpty()) {
2199         if (Frame* targetFrame = findFrameForNavigation(frameName))
2200             targetFrame->loader()->loadURL(newURL, referrer, String(), lockHistory, newLoadType, event, formState);
2201         else
2202             checkNewWindowPolicy(action, request, formState, frameName);
2203         return;
2204     }
2205
2206     RefPtr<DocumentLoader> oldDocumentLoader = m_documentLoader;
2207
2208     bool sameURL = shouldTreatURLAsSameAsCurrent(newURL);
2209     
2210     // Make sure to do scroll to anchor processing even if the URL is
2211     // exactly the same so pages with '#' links and DHTML side effects
2212     // work properly.
2213     if (shouldScrollToAnchor(isFormSubmission, newLoadType, newURL)) {
2214         oldDocumentLoader->setTriggeringAction(action);
2215         stopPolicyCheck();
2216         checkNavigationPolicy(request, oldDocumentLoader.get(), formState,
2217             callContinueFragmentScrollAfterNavigationPolicy, this);
2218     } else {
2219         // must grab this now, since this load may stop the previous load and clear this flag
2220         bool isRedirect = m_quickRedirectComing;
2221         loadWithNavigationAction(request, action, lockHistory, newLoadType, formState);
2222         if (isRedirect) {
2223             m_quickRedirectComing = false;
2224             if (m_provisionalDocumentLoader)
2225                 m_provisionalDocumentLoader->setIsClientRedirect(true);
2226         } else if (sameURL)
2227             // Example of this case are sites that reload the same URL with a different cookie
2228             // driving the generated content, or a master frame with links that drive a target
2229             // frame, where the user has clicked on the same link repeatedly.
2230             m_loadType = FrameLoadTypeSame;
2231     }
2232 }
2233
2234 void FrameLoader::load(const ResourceRequest& request, bool lockHistory)
2235 {
2236     load(request, SubstituteData(), lockHistory);
2237 }
2238
2239 void FrameLoader::load(const ResourceRequest& request, const SubstituteData& substituteData, bool lockHistory)
2240 {
2241     if (m_inStopAllLoaders)
2242         return;
2243         
2244     // FIXME: is this the right place to reset loadType? Perhaps this should be done after loading is finished or aborted.
2245     m_loadType = FrameLoadTypeStandard;
2246     RefPtr<DocumentLoader> loader = m_client->createDocumentLoader(request, substituteData);
2247     if (lockHistory && m_documentLoader)
2248         loader->setClientRedirectSourceForHistory(m_documentLoader->didCreateGlobalHistoryEntry() ? m_documentLoader->urlForHistory() : m_documentLoader->clientRedirectSourceForHistory());
2249     load(loader.get());
2250 }
2251
2252 void FrameLoader::load(const ResourceRequest& request, const String& frameName, bool lockHistory)
2253 {
2254     if (frameName.isEmpty()) {
2255         load(request, lockHistory);
2256         return;
2257     }
2258
2259     Frame* frame = findFrameForNavigation(frameName);
2260     if (frame) {
2261         frame->loader()->load(request, lockHistory);
2262         return;
2263     }
2264
2265     checkNewWindowPolicy(NavigationAction(request.url(), NavigationTypeOther), request, 0, frameName);
2266 }
2267
2268 void FrameLoader::loadWithNavigationAction(const ResourceRequest& request, const NavigationAction& action, bool lockHistory, FrameLoadType type, PassRefPtr<FormState> formState)
2269 {
2270     RefPtr<DocumentLoader> loader = m_client->createDocumentLoader(request, SubstituteData());
2271     if (lockHistory && m_documentLoader)
2272         loader->setClientRedirectSourceForHistory(m_documentLoader->didCreateGlobalHistoryEntry() ? m_documentLoader->urlForHistory() : m_documentLoader->clientRedirectSourceForHistory());
2273
2274     loader->setTriggeringAction(action);
2275     if (m_documentLoader)
2276         loader->setOverrideEncoding(m_documentLoader->overrideEncoding());
2277
2278     loadWithDocumentLoader(loader.get(), type, formState);
2279 }
2280
2281 void FrameLoader::load(DocumentLoader* newDocumentLoader)
2282 {
2283     ResourceRequest& r = newDocumentLoader->request();
2284     addExtraFieldsToMainResourceRequest(r);
2285     FrameLoadType type;
2286
2287     if (shouldTreatURLAsSameAsCurrent(newDocumentLoader->originalRequest().url())) {
2288         r.setCachePolicy(ReloadIgnoringCacheData);
2289         type = FrameLoadTypeSame;
2290     } else
2291         type = FrameLoadTypeStandard;
2292
2293     if (m_documentLoader)
2294         newDocumentLoader->setOverrideEncoding(m_documentLoader->overrideEncoding());
2295     
2296     // When we loading alternate content for an unreachable URL that we're
2297     // visiting in the history list, we treat it as a reload so the history list 
2298     // is appropriately maintained.
2299     //
2300     // FIXME: This seems like a dangerous overloading of the meaning of "FrameLoadTypeReload" ...
2301     // shouldn't a more explicit type of reload be defined, that means roughly 
2302     // "load without affecting history" ? 
2303     if (shouldReloadToHandleUnreachableURL(newDocumentLoader)) {
2304         ASSERT(type == FrameLoadTypeStandard);
2305         type = FrameLoadTypeReload;
2306     }
2307
2308     loadWithDocumentLoader(newDocumentLoader, type, 0);
2309 }
2310
2311 void FrameLoader::loadWithDocumentLoader(DocumentLoader* loader, FrameLoadType type, PassRefPtr<FormState> prpFormState)
2312 {
2313     ASSERT(m_client->hasWebView());
2314
2315     // Unfortunately the view must be non-nil, this is ultimately due
2316     // to parser requiring a FrameView.  We should fix this dependency.
2317
2318     ASSERT(m_frame->view());
2319
2320     m_policyLoadType = type;
2321     RefPtr<FormState> formState = prpFormState;
2322     bool isFormSubmission = formState;
2323
2324     const KURL& newURL = loader->request().url();
2325
2326     if (shouldScrollToAnchor(isFormSubmission, m_policyLoadType, newURL)) {
2327         RefPtr<DocumentLoader> oldDocumentLoader = m_documentLoader;
2328         NavigationAction action(newURL, m_policyLoadType, isFormSubmission);
2329
2330         oldDocumentLoader->setTriggeringAction(action);
2331         stopPolicyCheck();
2332         checkNavigationPolicy(loader->request(), oldDocumentLoader.get(), formState,
2333             callContinueFragmentScrollAfterNavigationPolicy, this);
2334     } else {
2335         if (Frame* parent = m_frame->tree()->parent())
2336             loader->setOverrideEncoding(parent->loader()->documentLoader()->overrideEncoding());
2337
2338         stopPolicyCheck();
2339         setPolicyDocumentLoader(loader);
2340
2341         checkNavigationPolicy(loader->request(), loader, formState,
2342             callContinueLoadAfterNavigationPolicy, this);
2343     }
2344 }
2345
2346 bool FrameLoader::canLoad(const KURL& url, const String& referrer, const Document* doc)
2347 {
2348     // We can always load any URL that isn't considered local (e.g. http URLs)
2349     if (!shouldTreatURLAsLocal(url.string()))
2350         return true;
2351
2352     // If we were provided a document, we let its local file policy dictate the result,
2353     // otherwise we allow local loads only if the supplied referrer is also local.
2354     if (doc)
2355         return doc->securityOrigin()->canLoadLocalResources();
2356     else if (!referrer.isEmpty())
2357         return shouldTreatURLAsLocal(referrer);
2358     else
2359         return false;
2360 }
2361
2362 void FrameLoader::reportLocalLoadFailed(Frame* frame, const String& url)
2363 {
2364     ASSERT(!url.isEmpty());
2365     if (!frame)
2366         return;
2367
2368     frame->domWindow()->console()->addMessage(JSMessageSource, ErrorMessageLevel, "Not allowed to load local resource: " + url, 0, String());
2369 }
2370
2371 bool FrameLoader::shouldHideReferrer(const KURL& url, const String& referrer)
2372 {
2373     bool referrerIsSecureURL = protocolIs(referrer, "https");
2374     bool referrerIsWebURL = referrerIsSecureURL || protocolIs(referrer, "http");
2375
2376     if (!referrerIsWebURL)
2377         return true;
2378
2379     if (!referrerIsSecureURL)
2380         return false;
2381
2382     bool URLIsSecureURL = url.protocolIs("https");
2383
2384     return !URLIsSecureURL;
2385 }
2386
2387 const ResourceRequest& FrameLoader::initialRequest() const
2388 {
2389     return activeDocumentLoader()->originalRequest();
2390 }
2391
2392 void FrameLoader::receivedData(const char* data, int length)
2393 {
2394     activeDocumentLoader()->receivedData(data, length);
2395 }
2396
2397 void FrameLoader::handleUnimplementablePolicy(const ResourceError& error)
2398 {
2399     m_delegateIsHandlingUnimplementablePolicy = true;
2400     m_client->dispatchUnableToImplementPolicy(error);
2401     m_delegateIsHandlingUnimplementablePolicy = false;
2402 }
2403
2404 void FrameLoader::cannotShowMIMEType(const ResourceResponse& response)
2405 {
2406     handleUnimplementablePolicy(m_client->cannotShowMIMETypeError(response));
2407 }
2408
2409 ResourceError FrameLoader::interruptionForPolicyChangeError(const ResourceRequest& request)
2410 {
2411     return m_client->interruptForPolicyChangeError(request);
2412 }
2413
2414 void FrameLoader::checkNavigationPolicy(const ResourceRequest& newRequest, NavigationPolicyDecisionFunction function, void* argument)
2415 {
2416     checkNavigationPolicy(newRequest, activeDocumentLoader(), 0, function, argument);
2417 }
2418
2419 void FrameLoader::checkContentPolicy(const String& MIMEType, ContentPolicyDecisionFunction function, void* argument)
2420 {
2421     ASSERT(activeDocumentLoader());
2422     
2423     // Always show content with valid substitute data.
2424     if (activeDocumentLoader()->substituteData().isValid()) {
2425         function(argument, PolicyUse);
2426         return;
2427     }
2428
2429 #if ENABLE(FTPDIR)
2430     // Respect the hidden FTP Directory Listing pref so it can be tested even if the policy delegate might otherwise disallow it
2431     Settings* settings = m_frame->settings();
2432     if (settings && settings->forceFTPDirectoryListings() && MIMEType == "application/x-ftp-directory") {
2433         function(argument, PolicyUse);
2434         return;
2435     }
2436 #endif
2437
2438     m_policyCheck.set(function, argument);
2439     m_client->dispatchDecidePolicyForMIMEType(&FrameLoader::continueAfterContentPolicy,
2440         MIMEType, activeDocumentLoader()->request());
2441 }
2442
2443 bool FrameLoader::shouldReloadToHandleUnreachableURL(DocumentLoader* docLoader)
2444 {
2445     KURL unreachableURL = docLoader->unreachableURL();
2446
2447     if (unreachableURL.isEmpty())
2448         return false;
2449
2450     if (!isBackForwardLoadType(m_policyLoadType))
2451         return false;
2452
2453     // We only treat unreachableURLs specially during the delegate callbacks
2454     // for provisional load errors and navigation policy decisions. The former
2455     // case handles well-formed URLs that can't be loaded, and the latter
2456     // case handles malformed URLs and unknown schemes. Loading alternate content
2457     // at other times behaves like a standard load.
2458     DocumentLoader* compareDocumentLoader = 0;
2459     if (m_delegateIsDecidingNavigationPolicy || m_delegateIsHandlingUnimplementablePolicy)
2460         compareDocumentLoader = m_policyDocumentLoader.get();
2461     else if (m_delegateIsHandlingProvisionalLoadError)
2462         compareDocumentLoader = m_provisionalDocumentLoader.get();
2463
2464     return compareDocumentLoader && unreachableURL == compareDocumentLoader->request().url();
2465 }
2466
2467 void FrameLoader::reloadWithOverrideEncoding(const String& encoding)
2468 {
2469     if (!m_documentLoader)
2470         return;
2471
2472     ResourceRequest request = m_documentLoader->request();
2473     KURL unreachableURL = m_documentLoader->unreachableURL();
2474     if (!unreachableURL.isEmpty())
2475         request.setURL(unreachableURL);
2476
2477     request.setCachePolicy(ReturnCacheDataElseLoad);
2478
2479     RefPtr<DocumentLoader> loader = m_client->createDocumentLoader(request, SubstituteData());
2480     setPolicyDocumentLoader(loader.get());
2481
2482     loader->setOverrideEncoding(encoding);
2483
2484     loadWithDocumentLoader(loader.get(), FrameLoadTypeReload, 0);
2485 }
2486
2487 void FrameLoader::reload(bool endToEndReload)
2488 {
2489     if (!m_documentLoader)
2490         return;
2491
2492     // If a window is created by javascript, its main frame can have an empty but non-nil URL.
2493     // Reloading in this case will lose the current contents (see 4151001).
2494     if (m_documentLoader->request().url().isEmpty())
2495         return;
2496
2497     ResourceRequest initialRequest = m_documentLoader->request();
2498
2499     // Replace error-page URL with the URL we were trying to reach.
2500     KURL unreachableURL = m_documentLoader->unreachableURL();
2501     if (!unreachableURL.isEmpty())
2502         initialRequest.setURL(unreachableURL);
2503     
2504     // Create a new document loader for the reload, this will become m_documentLoader eventually,
2505     // but first it has to be the "policy" document loader, and then the "provisional" document loader.
2506     RefPtr<DocumentLoader> loader = m_client->createDocumentLoader(initialRequest, SubstituteData());
2507
2508     ResourceRequest& request = loader->request();
2509
2510     // FIXME: We don't have a mechanism to revalidate the main resource without reloading at the moment.
2511     request.setCachePolicy(ReloadIgnoringCacheData);
2512
2513     // If we're about to re-post, set up action so the application can warn the user.
2514     if (request.httpMethod() == "POST")
2515         loader->setTriggeringAction(NavigationAction(request.url(), NavigationTypeFormResubmitted));
2516
2517     loader->setOverrideEncoding(m_documentLoader->overrideEncoding());
2518     
2519     loadWithDocumentLoader(loader.get(), endToEndReload ? FrameLoadTypeReloadFromOrigin : FrameLoadTypeReload, 0);
2520 }
2521
2522 static bool canAccessAncestor(const SecurityOrigin* activeSecurityOrigin, Frame* targetFrame)
2523 {
2524     // targetFrame can be NULL when we're trying to navigate a top-level frame
2525     // that has a NULL opener.
2526     if (!targetFrame)
2527         return false;
2528
2529     for (Frame* ancestorFrame = targetFrame; ancestorFrame; ancestorFrame = ancestorFrame->tree()->parent()) {
2530         Document* ancestorDocument = ancestorFrame->document();
2531         if (!ancestorDocument)
2532             return true;
2533
2534         const SecurityOrigin* ancestorSecurityOrigin = ancestorDocument->securityOrigin();
2535         if (activeSecurityOrigin->canAccess(ancestorSecurityOrigin))
2536             return true;
2537     }
2538
2539     return false;
2540 }
2541
2542 bool FrameLoader::shouldAllowNavigation(Frame* targetFrame) const
2543 {
2544     // The navigation change is safe if the active frame is:
2545     //   - in the same security origin as the target or one of the target's
2546     //     ancestors.
2547     //
2548     // Or the target frame is:
2549     //   - a top-level frame in the frame hierarchy and the active frame can
2550     //     navigate the target frame's opener per above.
2551
2552     if (!targetFrame)
2553         return true;
2554
2555     // Performance optimization.
2556     if (m_frame == targetFrame)
2557         return true;
2558
2559     // Let a frame navigate the top-level window that contains it.  This is
2560     // important to allow because it lets a site "frame-bust" (escape from a
2561     // frame created by another web site).
2562     if (targetFrame == m_frame->tree()->top())
2563         return true;
2564
2565     Document* activeDocument = m_frame->document();
2566     ASSERT(activeDocument);
2567     const SecurityOrigin* activeSecurityOrigin = activeDocument->securityOrigin();
2568
2569     // For top-level windows, check the opener.
2570     if (!targetFrame->tree()->parent() && canAccessAncestor(activeSecurityOrigin, targetFrame->loader()->opener()))
2571         return true;
2572
2573     // In general, check the frame's ancestors.
2574     if (canAccessAncestor(activeSecurityOrigin, targetFrame))
2575         return true;
2576
2577     Settings* settings = targetFrame->settings();
2578     if (settings && !settings->privateBrowsingEnabled()) {
2579         Document* targetDocument = targetFrame->document();
2580         // FIXME: this error message should contain more specifics of why the navigation change is not allowed.
2581         String message = String::format("Unsafe JavaScript attempt to initiate a navigation change for frame with URL %s from frame with URL %s.\n",
2582             targetDocument->url().string().utf8().data(), activeDocument->url().string().utf8().data());
2583
2584         // FIXME: should we print to the console of the activeFrame as well?
2585         targetFrame->domWindow()->console()->addMessage(JSMessageSource, ErrorMessageLevel, message, 1, String());
2586     }
2587     
2588     return false;
2589 }
2590
2591 void FrameLoader::stopLoadingSubframes()
2592 {
2593     for (RefPtr<Frame> child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
2594         child->loader()->stopAllLoaders();
2595 }
2596
2597 void FrameLoader::stopAllLoaders()
2598 {
2599     // If this method is called from within this method, infinite recursion can occur (3442218). Avoid this.
2600     if (m_inStopAllLoaders)
2601         return;
2602
2603     m_inStopAllLoaders = true;
2604
2605     stopPolicyCheck();
2606
2607     stopLoadingSubframes();
2608     if (m_provisionalDocumentLoader)
2609         m_provisionalDocumentLoader->stopLoading();
2610     if (m_documentLoader)
2611         m_documentLoader->stopLoading();
2612
2613     setProvisionalDocumentLoader(0);
2614     
2615     if (m_documentLoader)
2616         m_documentLoader->clearArchiveResources();
2617
2618     m_inStopAllLoaders = false;    
2619 }
2620
2621 void FrameLoader::stopForUserCancel(bool deferCheckLoadComplete)
2622 {
2623     stopAllLoaders();
2624     
2625     if (deferCheckLoadComplete)
2626         scheduleCheckLoadComplete();
2627     else if (m_frame->page())
2628         checkLoadComplete();
2629 }
2630
2631 DocumentLoader* FrameLoader::activeDocumentLoader() const
2632 {
2633     if (m_state == FrameStateProvisional)
2634         return m_provisionalDocumentLoader.get();
2635     return m_documentLoader.get();
2636 }
2637
2638 bool FrameLoader::isLoading() const
2639 {
2640     DocumentLoader* docLoader = activeDocumentLoader();
2641     if (!docLoader)
2642         return false;
2643     return docLoader->isLoadingMainResource() || docLoader->isLoadingSubresources() || docLoader->isLoadingPlugIns();
2644 }
2645
2646 bool FrameLoader::frameHasLoaded() const
2647 {
2648     return m_committedFirstRealDocumentLoad || (m_provisionalDocumentLoader && !m_creatingInitialEmptyDocument); 
2649 }
2650
2651 void FrameLoader::setDocumentLoader(DocumentLoader* loader)
2652 {
2653     if (!loader && !m_documentLoader)
2654         return;
2655     
2656     ASSERT(loader != m_documentLoader);
2657     ASSERT(!loader || loader->frameLoader() == this);
2658
2659     m_client->prepareForDataSourceReplacement();
2660     detachChildren();
2661     if (m_documentLoader)
2662         m_documentLoader->detachFromFrame();
2663
2664     m_documentLoader = loader;
2665 }
2666
2667 void FrameLoader::setPolicyDocumentLoader(DocumentLoader* loader)
2668 {
2669     if (m_policyDocumentLoader == loader)
2670         return;
2671
2672     ASSERT(m_frame);
2673     if (loader)
2674         loader->setFrame(m_frame);
2675     if (m_policyDocumentLoader
2676             && m_policyDocumentLoader != m_provisionalDocumentLoader
2677             && m_policyDocumentLoader != m_documentLoader)
2678         m_policyDocumentLoader->detachFromFrame();
2679
2680     m_policyDocumentLoader = loader;
2681 }
2682
2683 void FrameLoader::setProvisionalDocumentLoader(DocumentLoader* loader)
2684 {
2685     ASSERT(!loader || !m_provisionalDocumentLoader);
2686     ASSERT(!loader || loader->frameLoader() == this);
2687
2688     if (m_provisionalDocumentLoader && m_provisionalDocumentLoader != m_documentLoader)
2689         m_provisionalDocumentLoader->detachFromFrame();
2690
2691     m_provisionalDocumentLoader = loader;
2692 }
2693
2694 double FrameLoader::timeOfLastCompletedLoad()
2695 {
2696     return storedTimeOfLastCompletedLoad;
2697 }
2698
2699 void FrameLoader::setState(FrameState newState)
2700 {    
2701     m_state = newState;
2702     
2703     if (newState == FrameStateProvisional)
2704         provisionalLoadStarted();
2705     else if (newState == FrameStateComplete) {
2706         frameLoadCompleted();
2707         storedTimeOfLastCompletedLoad = currentTime();
2708         if (m_documentLoader)
2709             m_documentLoader->stopRecordingResponses();
2710     }
2711 }
2712
2713 void FrameLoader::clearProvisionalLoad()
2714 {
2715     setProvisionalDocumentLoader(0);
2716     if (Page* page = m_frame->page())
2717         page->progress()->progressCompleted(m_frame);
2718     setState(FrameStateComplete);
2719 }
2720
2721 void FrameLoader::markLoadComplete()
2722 {
2723     setState(FrameStateComplete);
2724 }
2725
2726 void FrameLoader::commitProvisionalLoad(PassRefPtr<CachedPage> prpCachedPage)
2727 {
2728     RefPtr<CachedPage> cachedPage = prpCachedPage;
2729     RefPtr<DocumentLoader> pdl = m_provisionalDocumentLoader;
2730
2731     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());
2732
2733     // Check to see if we need to cache the page we are navigating away from into the back/forward cache.
2734     // We are doing this here because we know for sure that a new page is about to be loaded.
2735     cachePageForHistoryItem(m_currentHistoryItem.get());
2736     
2737     if (m_loadType != FrameLoadTypeReplace)
2738         closeOldDataSources();
2739     
2740     if (!cachedPage && !m_creatingInitialEmptyDocument)
2741         m_client->makeRepresentation(pdl.get());
2742     
2743     transitionToCommitted(cachedPage);
2744     
2745     // Call clientRedirectCancelledOrFinished() here so that the frame load delegate is notified that the redirect's
2746     // status has changed, if there was a redirect.  The frame load delegate may have saved some state about
2747     // the redirect in its -webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:.  Since we are
2748     // just about to commit a new page, there cannot possibly be a pending redirect at this point.
2749     if (m_sentRedirectNotification)
2750         clientRedirectCancelledOrFinished(false);
2751     
2752     if (cachedPage && cachedPage->document()) {
2753         open(*cachedPage);
2754         cachedPage->clear();
2755     } else {        
2756         KURL url = pdl->substituteData().responseURL();
2757         if (url.isEmpty())
2758             url = pdl->url();
2759         if (url.isEmpty())
2760             url = pdl->responseURL();
2761         if (url.isEmpty())
2762             url = blankURL();
2763
2764         didOpenURL(url);
2765     }
2766
2767     LOG(Loading, "WebCoreLoading %s: Finished committing provisional load to URL %s", m_frame->tree()->name().string().utf8().data(), m_URL.string().utf8().data());
2768
2769     if (m_loadType == FrameLoadTypeStandard && m_documentLoader->isClientRedirect())
2770         updateHistoryForClientRedirect();
2771
2772     if (m_documentLoader->isLoadingFromCachedPage()) {
2773         m_frame->document()->documentDidBecomeActive();
2774         
2775         // Force a layout to update view size and thereby update scrollbars.
2776         m_client->forceLayout();
2777
2778         const ResponseVector& responses = m_documentLoader->responses();
2779         size_t count = responses.size();
2780         for (size_t i = 0; i < count; i++) {
2781             const ResourceResponse& response = responses[i];
2782             // FIXME: If the WebKit client changes or cancels the request, this is not respected.
2783             ResourceError error;
2784             unsigned long identifier;
2785             ResourceRequest request(response.url());
2786             requestFromDelegate(request, identifier, error);
2787             // FIXME: If we get a resource with more than 2B bytes, this code won't do the right thing.
2788             // However, with today's computers and networking speeds, this won't happen in practice.
2789             // Could be an issue with a giant local file.
2790             sendRemainingDelegateMessages(identifier, response, static_cast<int>(response.expectedContentLength()), error);
2791         }
2792         
2793         pageCache()->remove(m_currentHistoryItem.get());
2794
2795         m_documentLoader->setPrimaryLoadComplete(true);
2796
2797         // FIXME: Why only this frame and not parent frames?
2798         checkLoadCompleteForThisFrame();
2799     }
2800 }
2801
2802 void FrameLoader::transitionToCommitted(PassRefPtr<CachedPage> cachedPage)
2803 {
2804     ASSERT(m_client->hasWebView());
2805     ASSERT(m_state == FrameStateProvisional);
2806
2807     if (m_state != FrameStateProvisional)
2808         return;
2809
2810     m_client->setCopiesOnScroll();
2811     updateHistoryForCommit();
2812
2813     // The call to closeURL() invokes the unload event handler, which can execute arbitrary
2814     // JavaScript. If the script initiates a new load, we need to abandon the current load,
2815     // or the two will stomp each other.
2816     DocumentLoader* pdl = m_provisionalDocumentLoader.get();
2817     if (m_documentLoader)
2818         closeURL();
2819     if (pdl != m_provisionalDocumentLoader)
2820         return;
2821
2822     // Nothing else can interupt this commit - set the Provisional->Committed transition in stone
2823     if (m_documentLoader)
2824         m_documentLoader->stopLoadingSubresources();
2825     if (m_documentLoader)
2826         m_documentLoader->stopLoadingPlugIns();
2827
2828     setDocumentLoader(m_provisionalDocumentLoader.get());
2829     setProvisionalDocumentLoader(0);
2830     setState(FrameStateCommittedPage);
2831
2832     // Handle adding the URL to the back/forward list.
2833     DocumentLoader* dl = m_documentLoader.get();
2834     String ptitle = dl->title(); 
2835
2836     switch (m_loadType) {
2837         case FrameLoadTypeForward:
2838         case FrameLoadTypeBack:
2839         case FrameLoadTypeIndexedBackForward:
2840             if (Page* page = m_frame->page())
2841                 if (page->backForwardList()) {
2842                     updateHistoryForBackForwardNavigation();
2843
2844                     // Create a document view for this document, or used the cached view.
2845                     if (cachedPage) {
2846                         DocumentLoader* cachedDocumentLoader = cachedPage->documentLoader();
2847                         ASSERT(cachedDocumentLoader);
2848                         cachedDocumentLoader->setFrame(m_frame);
2849                         m_client->transitionToCommittedFromCachedFrame(cachedPage->cachedMainFrame());
2850                         
2851                     } else
2852                         m_client->transitionToCommittedForNewPage();
2853                 }
2854             break;
2855
2856         case FrameLoadTypeReload:
2857         case FrameLoadTypeReloadFromOrigin:
2858         case FrameLoadTypeSame:
2859         case FrameLoadTypeReplace:
2860             updateHistoryForReload();
2861             m_client->transitionToCommittedForNewPage();
2862             break;
2863
2864         case FrameLoadTypeStandard:
2865             updateHistoryForStandardLoad();
2866 #ifndef BUILDING_ON_TIGER
2867             // This code was originally added for a Leopard performance imporvement. We decided to 
2868             // ifdef it to fix correctness issues on Tiger documented in <rdar://problem/5441823>.
2869             if (m_frame->view())
2870                 m_frame->view()->setScrollbarsSuppressed(true);
2871 #endif
2872             m_client->transitionToCommittedForNewPage();
2873             break;
2874
2875         case FrameLoadTypeRedirectWithLockedBackForwardList:
2876             updateHistoryForRedirectWithLockedBackForwardList();
2877             m_client->transitionToCommittedForNewPage();
2878             break;
2879
2880         // FIXME Remove this check when dummy ds is removed (whatever "dummy ds" is).
2881         // An exception should be thrown if we're in the FrameLoadTypeUninitialized state.
2882         default:
2883             ASSERT_NOT_REACHED();
2884     }
2885
2886     m_responseMIMEType = dl->responseMIMEType();
2887
2888     // Tell the client we've committed this URL.
2889     ASSERT(m_frame->view());
2890
2891     if (m_creatingInitialEmptyDocument)
2892         return;
2893     
2894     m_committedFirstRealDocumentLoad = true;
2895
2896     // For non-cached HTML pages, these methods are called in FrameLoader::begin.
2897     if (cachedPage || !m_client->hasHTMLView()) {
2898         dispatchDidCommitLoad(); 
2899             
2900         // If we have a title let the WebView know about it. 
2901         if (!ptitle.isNull()) 
2902             m_client->dispatchDidReceiveTitle(ptitle);         
2903     }
2904 }
2905
2906 void FrameLoader::clientRedirectCancelledOrFinished(bool cancelWithLoadInProgress)
2907 {
2908     // Note that -webView:didCancelClientRedirectForFrame: is called on the frame load delegate even if
2909     // the redirect succeeded.  We should either rename this API, or add a new method, like
2910     // -webView:didFinishClientRedirectForFrame:
2911     m_client->dispatchDidCancelClientRedirect();
2912
2913     if (!cancelWithLoadInProgress)
2914         m_quickRedirectComing = false;
2915
2916     m_sentRedirectNotification = false;
2917 }
2918
2919 void FrameLoader::clientRedirected(const KURL& url, double seconds, double fireDate, bool lockBackForwardList, bool isJavaScriptFormAction)
2920 {
2921     m_client->dispatchWillPerformClientRedirect(url, seconds, fireDate);
2922     
2923     // Remember that we sent a redirect notification to the frame load delegate so that when we commit
2924     // the next provisional load, we can send a corresponding -webView:didCancelClientRedirectForFrame:
2925     m_sentRedirectNotification = true;
2926     
2927     // If a "quick" redirect comes in an, we set a special mode so we treat the next
2928     // load as part of the same navigation. If we don't have a document loader, we have
2929     // no "original" load on which to base a redirect, so we treat the redirect as a normal load.
2930     m_quickRedirectComing = lockBackForwardList && m_documentLoader && !isJavaScriptFormAction;
2931 }
2932
2933 #if ENABLE(WML)
2934 void FrameLoader::setForceReloadWmlDeck(bool reload)
2935 {
2936     m_forceReloadWmlDeck = reload;
2937 }
2938 #endif
2939
2940 bool FrameLoader::shouldReload(const KURL& currentURL, const KURL& destinationURL)
2941 {
2942 #if ENABLE(WML)
2943     // As for WML deck, sometimes it's supposed to be reloaded even if the same URL with fragment
2944     if (m_forceReloadWmlDeck)
2945         return true;
2946 #endif
2947
2948     // This function implements the rule: "Don't reload if navigating by fragment within
2949     // the same URL, but do reload if going to a new URL or to the same URL with no
2950     // fragment identifier at all."
2951     if (!destinationURL.hasRef())
2952         return true;
2953     return !equalIgnoringRef(currentURL, destinationURL);
2954 }
2955
2956 void FrameLoader::closeOldDataSources()
2957 {
2958     // FIXME: Is it important for this traversal to be postorder instead of preorder?
2959     // If so, add helpers for postorder traversal, and use them. If not, then lets not
2960     // use a recursive algorithm here.
2961     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
2962         child->loader()->closeOldDataSources();
2963     
2964     if (m_documentLoader)
2965         m_client->dispatchWillClose();
2966
2967     m_client->setMainFrameDocumentReady(false); // stop giving out the actual DOMDocument to observers
2968 }
2969
2970 void FrameLoader::open(CachedPage& cachedPage)
2971 {
2972     ASSERT(!m_frame->tree()->parent());
2973     ASSERT(m_frame->page());
2974     ASSERT(m_frame->page()->mainFrame() == m_frame);
2975
2976     cancelRedirection();
2977
2978     // We still have to close the previous part page.
2979     closeURL();
2980     
2981     // Delete old status bar messages (if it _was_ activated on last URL).
2982     if (m_frame->script()->isEnabled()) {
2983         m_frame->setJSStatusBarText(String());
2984         m_frame->setJSDefaultStatusBarText(String());
2985     }
2986
2987     open(*cachedPage.cachedMainFrame());
2988
2989     checkCompleted();
2990 }
2991
2992 void FrameLoader::open(CachedFrame& cachedFrame)
2993 {
2994     m_isComplete = false;
2995     
2996     // Don't re-emit the load event.
2997     m_didCallImplicitClose = true;
2998
2999     KURL url = cachedFrame.url();
3000
3001     if ((url.protocolIs("http") || url.protocolIs("https")) && !url.host().isEmpty() && url.path().isEmpty())
3002         url.setPath("/");
3003     
3004     m_URL = url;
3005     m_workingURL = url;
3006
3007     started();
3008
3009     clear();
3010
3011     Document* document = cachedFrame.document();
3012     ASSERT(document);
3013     document->setInPageCache(false);
3014
3015     m_needsClear = true;
3016     m_isComplete = false;
3017     m_didCallImplicitClose = false;
3018     m_outgoingReferrer = url.string();
3019
3020     FrameView* view = cachedFrame.view();
3021     
3022     // When navigating to a CachedFrame its FrameView should never be null.  If it is we'll crash in creative ways downstream.
3023     ASSERT(view);
3024     if (view)
3025         view->setWasScrolledByUser(false);
3026     m_frame->setView(view);
3027     
3028     m_frame->setDocument(document);
3029     m_frame->setDOMWindow(cachedFrame.domWindow());
3030     m_frame->domWindow()->setURL(document->url());
3031     m_frame->domWindow()->setSecurityOrigin(document->securityOrigin());
3032
3033     m_decoder = document->decoder();
3034
3035     updatePolicyBaseURL();
3036
3037     cachedFrame.restore();
3038 }
3039
3040 bool FrameLoader::isStopping() const
3041 {
3042     return activeDocumentLoader()->isStopping();
3043 }
3044
3045 void FrameLoader::finishedLoading()
3046 {
3047     // Retain because the stop may release the last reference to it.
3048     RefPtr<Frame> protect(m_frame);
3049
3050     RefPtr<DocumentLoader> dl = activeDocumentLoader();
3051     dl->finishedLoading();
3052     if (!dl->mainDocumentError().isNull() || !dl->frameLoader())
3053         return;
3054     dl->setPrimaryLoadComplete(true);
3055     m_client->dispatchDidLoadMainResource(dl.get());
3056     checkLoadComplete();
3057 }
3058
3059 bool FrameLoader::isHostedByObjectElement() const
3060 {
3061     HTMLFrameOwnerElement* owner = m_frame->ownerElement();
3062     return owner && owner->hasTagName(objectTag);
3063 }
3064
3065 bool FrameLoader::isLoadingMainFrame() const
3066 {
3067     Page* page = m_frame->page();
3068     return page && m_frame == page->mainFrame();
3069 }
3070
3071 bool FrameLoader::canShowMIMEType(const String& MIMEType) const
3072 {
3073     return m_client->canShowMIMEType(MIMEType);
3074 }
3075
3076 bool FrameLoader::representationExistsForURLScheme(const String& URLScheme)
3077 {
3078     return m_client->representationExistsForURLScheme(URLScheme);
3079 }
3080
3081 String FrameLoader::generatedMIMETypeForURLScheme(const String& URLScheme)
3082 {
3083     return m_client->generatedMIMETypeForURLScheme(URLScheme);
3084 }
3085
3086 void FrameLoader::cancelContentPolicyCheck()
3087 {
3088     m_client->cancelPolicyCheck();
3089     m_policyCheck.clear();
3090 }
3091
3092 void FrameLoader::didReceiveServerRedirectForProvisionalLoadForFrame()
3093 {
3094     m_client->dispatchDidReceiveServerRedirectForProvisionalLoad();
3095 }
3096
3097 void FrameLoader::finishedLoadingDocument(DocumentLoader* loader)
3098 {
3099     // FIXME: Platforms shouldn't differ here!
3100 #if PLATFORM(WIN) || PLATFORM(CHROMIUM)
3101     if (m_creatingInitialEmptyDocument)
3102         return;
3103 #endif
3104     
3105     // If loading a webarchive, run through webarchive machinery
3106     const String& responseMIMEType = loader->responseMIMEType();
3107
3108     // FIXME: Mac's FrameLoaderClient::finishedLoading() method does work that is required even with Archive loads
3109     // so we still need to call it.  Other platforms should only call finishLoading for non-archive loads
3110     // That work should be factored out so this #ifdef can be removed
3111 #if PLATFORM(MAC)
3112     m_client->finishedLoading(loader);
3113     if (!ArchiveFactory::isArchiveMimeType(responseMIMEType))
3114         return;
3115 #else
3116     if (!ArchiveFactory::isArchiveMimeType(responseMIMEType)) {
3117         m_client->finishedLoading(loader);
3118         return;
3119     }
3120 #endif
3121         
3122     RefPtr<Archive> archive(ArchiveFactory::create(loader->mainResourceData().get(), responseMIMEType));
3123     if (!archive)
3124         return;
3125
3126     loader->addAllArchiveResources(archive.get());
3127     
3128     ArchiveResource* mainResource = archive->mainResource();
3129     loader->setParsedArchiveData(mainResource->data());
3130     continueLoadWithData(mainResource->data(), mainResource->mimeType(), mainResource->textEncoding(), mainResource->url());
3131 }
3132
3133 bool FrameLoader::isReplacing() const
3134 {
3135     return m_loadType == FrameLoadTypeReplace;
3136 }
3137
3138 void FrameLoader::setReplacing()
3139 {
3140     m_loadType = FrameLoadTypeReplace;
3141 }
3142
3143 void FrameLoader::revertToProvisional(DocumentLoader* loader)
3144 {
3145     m_client->revertToProvisionalState(loader);
3146 }
3147
3148 bool FrameLoader::subframeIsLoading() const
3149 {
3150     // It's most likely that the last added frame is the last to load so we walk backwards.
3151     for (Frame* child = m_frame->tree()->lastChild(); child; child = child->tree()->previousSibling()) {
3152         FrameLoader* childLoader = child->loader();
3153         DocumentLoader* documentLoader = childLoader->documentLoader();
3154         if (documentLoader && documentLoader->isLoadingInAPISense())
3155             return true;
3156         documentLoader = childLoader->provisionalDocumentLoader();
3157         if (documentLoader && documentLoader->isLoadingInAPISense())
3158             return true;
3159     }
3160     return false;
3161 }
3162
3163 void FrameLoader::willChangeTitle(DocumentLoader* loader)
3164 {
3165     m_client->willChangeTitle(loader);
3166 }
3167
3168 FrameLoadType FrameLoader::loadType() const
3169 {
3170     return m_loadType;
3171 }
3172     
3173 CachePolicy FrameLoader::cachePolicy() const
3174 {
3175     if (m_isComplete)
3176         return CachePolicyVerify;
3177     
3178     if (m_loadType == FrameLoadTypeReloadFromOrigin || documentLoader()->request().cachePolicy() == ReloadIgnoringCacheData)
3179         return CachePolicyReload;
3180     
3181     if (Frame* parentFrame = m_frame->tree()->parent()) {
3182         CachePolicy parentCachePolicy = parentFrame->loader()->cachePolicy();
3183         if (parentCachePolicy != CachePolicyVerify)
3184             return parentCachePolicy;
3185     }
3186
3187     if (m_loadType == FrameLoadTypeReload)
3188         return CachePolicyRevalidate;
3189
3190     return CachePolicyVerify;
3191 }
3192
3193 void FrameLoader::stopPolicyCheck()
3194 {
3195     m_client->cancelPolicyCheck();
3196     PolicyCheck check = m_policyCheck;
3197     m_policyCheck.clear();
3198     check.cancel();
3199 }
3200
3201 void FrameLoader::checkLoadCompleteForThisFrame()
3202 {
3203     ASSERT(m_client->hasWebView());
3204
3205     switch (m_state) {
3206         case FrameStateProvisional: {
3207             if (m_delegateIsHandlingProvisionalLoadError)
3208                 return;
3209
3210             RefPtr<DocumentLoader> pdl = m_provisionalDocumentLoader;
3211             if (!pdl)
3212                 return;
3213                 
3214             // If we've received any errors we may be stuck in the provisional state and actually complete.
3215             const ResourceError& error = pdl->mainDocumentError();
3216             if (error.isNull())
3217                 return;
3218
3219             // Check all children first.
3220             RefPtr<HistoryItem> item;
3221             if (Page* page = m_frame->page())
3222                 if (isBackForwardLoadType(loadType()) && m_frame == page->mainFrame())
3223                     item = m_currentHistoryItem;
3224                 
3225             bool shouldReset = true;
3226             if (!pdl->isLoadingInAPISense()) {
3227                 m_delegateIsHandlingProvisionalLoadError = true;
3228                 m_client->dispatchDidFailProvisionalLoad(error);
3229                 m_delegateIsHandlingProvisionalLoadError = false;
3230
3231                 // FIXME: can stopping loading here possibly have any effect, if isLoading is false,
3232                 // which it must be to be in this branch of the if? And is it OK to just do a full-on
3233                 // stopAllLoaders instead of stopLoadingSubframes?
3234                 stopLoadingSubframes();
3235                 pdl->stopLoading();
3236
3237                 // Finish resetting the load state, but only if another load hasn't been started by the
3238                 // delegate callback.
3239                 if (pdl == m_provisionalDocumentLoader)
3240                     clearProvisionalLoad();
3241                 else if (m_provisionalDocumentLoader) {
3242                     KURL unreachableURL = m_provisionalDocumentLoader->unreachableURL();
3243                     if (!unreachableURL.isEmpty() && unreachableURL == pdl->request().url())
3244                         shouldReset = false;
3245                 }
3246             }
3247             if (shouldReset && item)
3248                 if (Page* page = m_frame->page()) {
3249                     page->backForwardList()->goToItem(item.get());
3250                     Settings* settings = m_frame->settings();
3251                     page->setGlobalHistoryItem((!settings || settings->privateBrowsingEnabled()) ? 0 : item.get());
3252                 }
3253             return;
3254         }
3255         
3256         case FrameStateCommittedPage: {
3257             DocumentLoader* dl = m_documentLoader.get();            
3258             if (!dl || dl->isLoadingInAPISense())
3259                 return;
3260
3261             markLoadComplete();
3262
3263             // FIXME: Is this subsequent work important if we already navigated away?
3264             // Maybe there are bugs because of that, or extra work we can skip because
3265             // the new page is ready.
3266
3267             m_client->forceLayoutForNonHTML();
3268              
3269             // If the user had a scroll point, scroll to it, overriding the anchor point if any.
3270             if (Page* page = m_frame->page())
3271                 if ((isBackForwardLoadType(m_loadType) || m_loadType == FrameLoadTypeReload || m_loadType == FrameLoadTypeReloadFromOrigin) && page->backForwardList())
3272                     restoreScrollPositionAndViewState();
3273
3274             if (m_creatingInitialEmptyDocument || !m_committedFirstRealDocumentLoad)
3275                 return;
3276
3277             const ResourceError& error = dl->mainDocumentError();
3278 #ifndef NDEBUG
3279             m_didDispatchDidCommitLoad = false;
3280 #endif
3281             if (!error.isNull())
3282                 m_client->dispatchDidFailLoad(error);
3283             else
3284                 m_client->dispatchDidFinishLoad();
3285
3286             if (Page* page = m_frame->page())
3287                 page->progress()->progressCompleted(m_frame);
3288             return;
3289         }
3290         
3291         case FrameStateComplete:
3292             frameLoadCompleted();
3293             return;
3294     }
3295
3296     ASSERT_NOT_REACHED();
3297 }
3298
3299 void FrameLoader::continueAfterContentPolicy(PolicyAction policy)
3300 {
3301     PolicyCheck check = m_policyCheck;
3302     m_policyCheck.clear();
3303     check.call(policy);
3304 }
3305
3306 void FrameLoader::continueLoadAfterWillSubmitForm(PolicyAction)
3307 {
3308     if (!m_provisionalDocumentLoader)
3309         return;
3310
3311     // DocumentLoader calls back to our prepareForLoadStart
3312     m_provisionalDocumentLoader->prepareForLoadStart();
3313     
3314     // The load might be cancelled inside of prepareForLoadStart(), nulling out the m_provisionalDocumentLoader, 
3315     // so we need to null check it again.
3316     if (!m_provisionalDocumentLoader)
3317         return;
3318
3319     DocumentLoader* activeDocLoader = activeDocumentLoader();
3320     if (activeDocLoader && activeDocLoader->isLoadingMainResource())
3321         return;
3322
3323     m_provisionalDocumentLoader->setLoadingFromCachedPage(false);
3324
3325     unsigned long identifier = 0;
3326
3327     if (Page* page = m_frame->page()) {
3328         identifier = page->progress()->createUniqueIdentifier();
3329         dispatchAssignIdentifierToInitialRequest(identifier, m_provisionalDocumentLoader.get(), m_provisionalDocumentLoader->originalRequest());
3330     }
3331
3332     if (!m_provisionalDocumentLoader->startLoadingMainResource(identifier))
3333         m_provisionalDocumentLoader->updateLoading();
3334 }
3335
3336 void FrameLoader::didFirstLayout()
3337 {
3338     if (Page* page = m_frame->page())
3339         if (isBackForwardLoadType(m_loadType) && page->backForwardList())
3340             restoreScrollPositionAndViewState();
3341
3342     m_firstLayoutDone = true;
3343     m_client->dispatchDidFirstLayout();
3344 }
3345
3346 void FrameLoader::didFirstVisuallyNonEmptyLayout()
3347 {
3348     m_client->dispatchDidFirstVisuallyNonEmptyLayout();
3349 }
3350
3351 void FrameLoader::frameLoadCompleted()
3352 {
3353     // Note: Can be called multiple times.
3354
3355     m_client->frameLoadCompleted();
3356
3357     // Even if already complete, we might have set a previous item on a frame that
3358     // didn't do any data loading on the past transaction. Make sure to clear these out.
3359     setPreviousHistoryItem(0);
3360
3361     // After a canceled provisional load, firstLayoutDone is false.
3362     // Reset it to true if we're displaying a page.
3363     if (m_documentLoader)
3364         m_firstLayoutDone = true;
3365 }
3366
3367 bool FrameLoader::firstLayoutDone() const
3368 {
3369     return m_firstLayoutDone;
3370 }
3371
3372 bool FrameLoader::isQuickRedirectComing() const
3373 {
3374     return m_quickRedirectComing;
3375 }
3376
3377 void FrameLoader::detachChildren()
3378 {
3379     // FIXME: Is it really necessary to do this in reverse order?
3380     Frame* previous;
3381     for (Frame* child = m_frame->tree()->lastChild(); child; child = previous) {
3382         previous = child->tree()->previousSibling();
3383         child->loader()->detachFromParent();
3384     }
3385 }
3386
3387 void FrameLoader::closeAndRemoveChild(Frame* child)
3388 {
3389     child->tree()->detachFromParent();
3390
3391     child->setView(0);
3392     if (child->ownerElement())
3393         child->page()->decrementFrameCount();
3394     child->pageDestroyed();
3395
3396     m_frame->tree()->removeChild(child);
3397 }
3398
3399 void FrameLoader::recursiveCheckLoadComplete()
3400 {
3401     Vector<RefPtr<Frame>, 10> frames;
3402     
3403     for (RefPtr<Frame> frame = m_frame->tree()->firstChild(); frame; frame = frame->tree()->nextSibling())
3404         frames.append(frame);
3405     
3406     unsigned size = frames.size();
3407     for (unsigned i = 0; i < size; i++)
3408         frames[i]->loader()->recursiveCheckLoadComplete();
3409     
3410     checkLoadCompleteForThisFrame();
3411 }
3412
3413 // Called every time a resource is completely loaded, or an error is received.
3414 void FrameLoader::checkLoadComplete()
3415 {
3416     ASSERT(m_client->hasWebView());
3417     
3418     // FIXME: Always traversing the entire frame tree is a bit inefficient, but 
3419     // is currently needed in order to null out the previous history item for all frames.
3420     if (Page* page = m_frame->page())
3421         page->mainFrame()->loader()->recursiveCheckLoadComplete();
3422 }
3423
3424 int FrameLoader::numPendingOrLoadingRequests(bool recurse) const
3425 {
3426     if (!recurse)
3427         return numRequests(m_frame->document());
3428
3429     int count = 0;
3430     for (Frame* frame = m_frame; frame; frame = frame->tree()->traverseNext(m_frame))
3431         count += numRequests(frame->document());
3432     return count;
3433 }
3434
3435 void FrameLoader::submitForm(const FrameLoadRequest& request, Event* event, bool lockHistory, bool lockBackForwardList)
3436 {
3437     // FIXME: We'd like to remove this altogether and fix the multiple form submission issue another way.
3438     // We do not want to submit more than one form from the same page,
3439     // nor do we want to submit a single form more than once.
3440     // This flag prevents these from happening; not sure how other browsers prevent this.
3441     // The flag is reset in each time we start handle a new mouse or key down event, and
3442     // also in setView since this part may get reused for a page from the back/forward cache.
3443     // The form multi-submit logic here is only needed when we are submitting a form that affects this frame.
3444     // FIXME: Frame targeting is only one of the ways the submission could end up doing something other
3445     // than replacing this frame's content, so this check is flawed. On the other hand, the check is hardly
3446     // needed any more now that we reset m_submittedFormURL on each mouse or key down event.
3447     Frame* target = m_frame->tree()->find(request.frameName());
3448     if (m_frame->tree()->isDescendantOf(target)) {
3449         if (m_submittedFormURL == request.resourceRequest().url())
3450             return;
3451         m_submittedFormURL = request.resourceRequest().url();
3452     }
3453
3454     loadFrameRequestWithFormAndValues(request, lockHistory, lockBackForwardList, event, m_formAboutToBeSubmitted.get(), m_formValuesAboutToBeSubmitted);
3455
3456     clearRecordedFormValues();
3457 }
3458
3459 String FrameLoader::userAgent(const KURL& url) const
3460 {
3461     return m_client->userAgent(url);
3462 }
3463
3464 void FrameLoader::tokenizerProcessedData()
3465 {
3466 //    ASSERT(m_frame->page());
3467 //    ASSERT(m_frame->document());
3468
3469     checkCompleted();
3470 }
3471
3472 void FrameLoader::handledOnloadEvents()
3473 {
3474     m_client->dispatchDidHandleOnloadEvents();
3475 }
3476
3477 void FrameLoader::frameDetached()
3478 {
3479     stopAllLoaders();
3480     m_frame->document()->stopActiveDOMObjects();
3481     detachFromParent();
3482 }
3483
3484 void FrameLoader::detachFromParent()
3485 {
3486     RefPtr<Frame> protect(m_frame);
3487
3488     closeURL();
3489     stopAllLoaders();
3490     saveScrollPositionAndViewStateToItem(currentHistoryItem());
3491     detachChildren();
3492
3493     if (Page* page = m_frame->page())
3494         page->inspectorController()->frameDetachedFromParent(m_frame);
3495
3496     m_client->detachedFromParent2();
3497     setDocumentLoader(0);
3498     m_client->detachedFromParent3();
3499     if (Frame* parent = m_frame->tree()->parent()) {
3500         parent->loader()->closeAndRemoveChild(m_frame);
3501         parent->loader()->scheduleCheckCompleted();
3502     } else {
3503         m_frame->setView(0);
3504         m_frame->pageDestroyed();
3505     }
3506 }
3507     
3508 void FrameLoader::addExtraFieldsToSubresourceRequest(ResourceRequest& request)
3509 {
3510     addExtraFieldsToRequest(request, m_loadType, false, false);
3511 }
3512
3513 void FrameLoader::addExtraFieldsToMainResourceRequest(ResourceRequest& request)
3514 {
3515     addExtraFieldsToRequest(request, m_loadType, true, false);
3516 }
3517
3518 void FrameLoader::addExtraFieldsToRequest(ResourceRequest& request, FrameLoadType loadType, bool mainResource, bool cookiePolicyURLFromRequest)
3519 {
3520     // Don't set the cookie policy URL if it's already been set.
3521     // But make sure to set it on all requests, as it has significance beyond the cookie policy for all protocols (<rdar://problem/6616664>).
3522     if (request.mainDocumentURL().isEmpty()) {
3523         if (mainResource && (isLoadingMainFrame() || cookiePolicyURLFromRequest))
3524             request.setMainDocumentURL(request.url());
3525         else if (Page* page = m_frame->page())
3526             request.setMainDocumentURL(page->mainFrame()->loader()->url());
3527     }
3528     
3529     // The remaining modifications are only necessary for HTTP and HTTPS.
3530     if (!request.url().isEmpty() && !request.url().protocolInHTTPFamily())
3531         return;
3532
3533     applyUserAgent(request);
3534     
3535     if (loadType == FrameLoadTypeReload) {
3536         request.setCachePolicy(ReloadIgnoringCacheData);
3537         request.setHTTPHeaderField("Cache-Control", "max-age=0");
3538     } else if (loadType == FrameLoadTypeReloadFromOrigin) {
3539         request.setCachePolicy(ReloadIgnoringCacheData);
3540         request.setHTTPHeaderField("Cache-Control", "no-cache");
3541         request.setHTTPHeaderField("Pragma", "no-cache");
3542     }
3543     
3544     if (mainResource)
3545         request.setHTTPAccept("application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5");
3546
3547     // Make sure we send the Origin header.
3548     addHTTPOriginIfNeeded(request, String());
3549
3550     // Always try UTF-8. If that fails, try frame encoding (if any) and then the default.
3551     // For a newly opened frame with an empty URL, encoding() should not be used, because this methods asks decoder, which uses ISO-8859-1.
3552     Settings* settings = m_frame->settings();
3553     request.setResponseContentDispositionEncodingFallbackArray("UTF-8", m_URL.isEmpty() ? m_encoding : encoding(), settings ? settings->defaultTextEncodingName() : String());
3554 }
3555
3556 void FrameLoader::addHTTPOriginIfNeeded(ResourceRequest& request, String origin)
3557 {
3558     if (!request.httpOrigin().isEmpty())
3559         return;  // Request already has an Origin header.
3560
3561     // Don't send an Origin header for GET or HEAD to avoid privacy issues.
3562     // For example, if an intranet page has a hyperlink to an external web
3563     // site, we don't want to include the Origin of the request because it
3564     // will leak the internal host name. Similar privacy concerns have lead
3565     // to the widespread suppression of the Referer header at the network
3566     // layer.
3567     if (request.httpMethod() == "GET" || request.httpMethod() == "HEAD")
3568         return;
3569
3570     // For non-GET and non-HEAD methods, always send an Origin header so the
3571     // server knows we support this feature.
3572
3573     if (origin.isEmpty()) {
3574         // If we don't know what origin header to attach, we attach the value
3575         // for an empty origin.
3576         origin = SecurityOrigin::createEmpty()->toString();
3577     }
3578
3579     request.setHTTPOrigin(origin);
3580 }
3581
3582 void FrameLoader::committedLoad(DocumentLoader* loader, const char* data, int length)
3583 {
3584     if (ArchiveFactory::isArchiveMimeType(loader->response().mimeType()))
3585         return;
3586     m_client->committedLoad(loader, data, length);
3587 }
3588
3589 void FrameLoader::loadPostRequest(const ResourceRequest& inRequest, const String& referrer, const String& frameName, bool lockHistory, FrameLoadType loadType, Event* event, PassRefPtr<FormState> prpFormState)
3590 {
3591     RefPtr<FormState> formState = prpFormState;
3592
3593     // When posting, use the NSURLRequestReloadIgnoringCacheData load flag.
3594     // This prevents a potential bug which may cause a page with a form that uses itself
3595     // as an action to be returned from the cache without submitting.
3596
3597     // FIXME: Where's the code that implements what the comment above says?
3598
3599     // Previously when this method was reached, the original FrameLoadRequest had been deconstructed to build a 
3600     // bunch of parameters that would come in here and then be built back up to a ResourceRequest.  In case
3601     // any caller depends on the immutability of the original ResourceRequest, I'm rebuilding a ResourceRequest
3602     // from scratch as it did all along.
3603     const KURL& url = inRequest.url();
3604     RefPtr<FormData> formData = inRequest.httpBody();
3605     const String& contentType = inRequest.httpContentType();
3606     String origin = inRequest.httpOrigin();
3607
3608     ResourceRequest workingResourceRequest(url);    
3609
3610     if (!referrer.isEmpty())
3611         workingResourceRequest.setHTTPReferrer(referrer);
3612     workingResourceRequest.setHTTPOrigin(origin);
3613     workingResourceRequest.setHTTPMethod("POST");
3614     workingResourceRequest.setHTTPBody(formData);
3615     workingResourceRequest.setHTTPContentType(contentType);
3616     addExtraFieldsToRequest(workingResourceRequest, loadType, true, true);
3617
3618     NavigationAction action(url, loadType, true, event);
3619
3620     if (!frameName.isEmpty()) {
3621         if (Frame* targetFrame = findFrameForNavigation(frameName))
3622             targetFrame->loader()->loadWithNavigationAction(workingResourceRequest, action, lockHistory, loadType, formState.release());
3623         else
3624             checkNewWindowPolicy(action, workingResourceRequest, formState.release(), frameName);
3625     } else
3626         loadWithNavigationAction(workingResourceRequest, action, lockHistory, loadType, formState.release());    
3627 }
3628
3629 void FrameLoader::loadEmptyDocumentSynchronously()
3630 {
3631     ResourceRequest request(KURL(""));
3632     load(request, false);
3633 }
3634
3635 unsigned long FrameLoader::loadResourceSynchronously(const ResourceRequest& request, ResourceError& error, ResourceResponse& response, Vector<char>& data)
3636 {
3637     // Since this is a subresource, we can load any URL (we ignore the return value).
3638     // But we still want to know whether we should hide the referrer or not, so we call the canLoad method.
3639     String referrer = m_outgoingReferrer;
3640     if (shouldHideReferrer(request.url(), referrer))
3641         referrer = String();
3642     
3643     ResourceRequest initialRequest = request;
3644     initialRequest.setTimeoutInterval(10);
3645     
3646     if (initialRequest.isConditional())
3647         initialRequest.setCachePolicy(ReloadIgnoringCacheData);
3648     else
3649         initialRequest.setCachePolicy(documentLoader()->request().cachePolicy());
3650     
3651     if (!referrer.isEmpty())
3652         initialRequest.setHTTPReferrer(referrer);
3653     addHTTPOriginIfNeeded(initialRequest, outgoingOrigin());
3654
3655     if (Page* page = m_frame->page())
3656         initialRequest.setMainDocumentURL(page->mainFrame()->loader()->documentLoader()->request().url());
3657     initialRequest.setHTTPUserAgent(client()->userAgent(request.url()));
3658
3659     unsigned long identifier = 0;    
3660     ResourceRequest newRequest(initialRequest);
3661     requestFromDelegate(newRequest, identifier, error);
3662
3663     if (error.isNull()) {
3664         ASSERT(!newRequest.isNull());
3665         
3666 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
3667         ApplicationCacheResource* resource;
3668         if (documentLoader()->shouldLoadResourceFromApplicationCache(newRequest, resource)) {
3669             if (resource) {
3670                 response = resource->response();
3671                 data.append(resource->data()->data(), resource->data()->size());
3672             } else
3673                 error = cannotShowURLError(newRequest);
3674         } else {
3675 #endif
3676             ResourceHandle::loadResourceSynchronously(newRequest, error, response, data, m_frame);
3677
3678 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
3679             // 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,
3680             // 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
3681             // corresponding to the matched namespace.
3682             if ((!error.isNull() && !error.isCancellation())
3683                  || response.httpStatusCode() / 100 == 4 || response.httpStatusCode() / 100 == 5
3684                  || !protocolHostAndPortAreEqual(newRequest.url(), response.url())) {
3685                 if (documentLoader()->getApplicationCacheFallbackResource(newRequest, resource)) {
3686                     response = resource->response();
3687                     data.clear();
3688                     data.append(resource->data()->data(), resource->data()->size());
3689                 }
3690             }
3691         }
3692 #endif
3693     }
3694     
3695     sendRemainingDelegateMessages(identifier, response, data.size(), error);
3696     return identifier;
3697 }
3698
3699 void FrameLoader::assignIdentifierToInitialRequest(unsigned long identifier, const ResourceRequest& clientRequest)
3700 {
3701     return dispatchAssignIdentifierToInitialRequest(identifier, activeDocumentLoader(), clientRequest);
3702 }
3703
3704 void FrameLoader::willSendRequest(ResourceLoader* loader, ResourceRequest& clientRequest, const ResourceResponse& redirectResponse)
3705 {
3706     applyUserAgent(clientRequest);
3707     dispatchWillSendRequest(loader->documentLoader(), loader->identifier(), clientRequest, redirectResponse);
3708 }
3709
3710 void FrameLoader::didReceiveResponse(ResourceLoader* loader, const ResourceResponse& r)
3711 {
3712     activeDocumentLoader()->addResponse(r);
3713     
3714     if (Page* page = m_frame->page())
3715         page->progress()->incrementProgress(loader->identifier(), r);
3716     dispatchDidReceiveResponse(loader->documentLoader(), loader->identifier(), r);
3717 }
3718
3719 void FrameLoader::didReceiveData(ResourceLoader* loader, const char* data, int length, int lengthReceived)
3720 {
3721     if (Page* page = m_frame->page())
3722         page->progress()->incrementProgress(loader->identifier(), data, length);
3723     dispatchDidReceiveContentLength(loader->documentLoader(), loader->identifier(), lengthReceived);
3724 }
3725
3726 void FrameLoader::didFailToLoad(ResourceLoader* loader, const ResourceError& error)
3727 {
3728     if (Page* page = m_frame->page())
3729         page->progress()->completeProgress(loader->identifier());
3730     if (!error.isNull())
3731         m_client->dispatchDidFailLoading(loader->documentLoader(), loader->identifier(), error);
3732 }
3733
3734 const ResourceRequest& FrameLoader::originalRequest() const
3735 {
3736     return activeDocumentLoader()->originalRequestCopy();
3737 }
3738
3739 void FrameLoader::receivedMainResourceError(const ResourceError& error, bool isComplete)
3740 {
3741     // Retain because the stop may release the last reference to it.
3742     RefPtr<Frame> protect(m_frame);
3743
3744     RefPtr<DocumentLoader> loader = activeDocumentLoader();
3745     
3746     if (isComplete) {
3747         // FIXME: Don't want to do this if an entirely new load is going, so should check
3748         // that both data sources on the frame are either this or nil.
3749         stop();
3750         if (m_client->shouldFallBack(error))
3751             handleFallbackContent();
3752     }
3753     
3754     if (m_state == FrameStateProvisional && m_provisionalDocumentLoader) {
3755         KURL failedURL = m_provisionalDocumentLoader->originalRequestCopy().url();
3756         didNotOpenURL(failedURL);
3757             
3758         // We might have made a page cache item, but now we're bailing out due to an error before we ever
3759         // transitioned to the new page (before WebFrameState == commit).  The goal here is to restore any state
3760         // so that the existing view (that wenever got far enough to replace) can continue being used.
3761         invalidateCurrentItemCachedPage();
3762         
3763         // Call clientRedirectCancelledOrFinished here so that the frame load delegate is notified that the redirect's
3764         // status has changed, if there was a redirect. The frame load delegate may have saved some state about
3765         // the redirect in its -webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:. Since we are definitely
3766         // not going to use this provisional resource, as it was cancelled, notify the frame load delegate that the redirect
3767         // has ended.
3768         if (m_sentRedirectNotification)
3769             clientRedirectCancelledOrFinished(false);
3770     }
3771     
3772     
3773     loader->mainReceivedError(error, isComplete);
3774 }
3775
3776 void FrameLoader::callContinueFragmentScrollAfterNavigationPolicy(void* argument,
3777     const ResourceRequest& request, PassRefPtr<FormState>, bool shouldContinue)
3778 {
3779     FrameLoader* loader = static_cast<FrameLoader*>(argument);
3780     loader->continueFragmentScrollAfterNavigationPolicy(request, shouldContinue);
3781 }
3782
3783 void FrameLoader::continueFragmentScrollAfterNavigationPolicy(const ResourceRequest& request, bool shouldContinue)
3784 {
3785     bool isRedirect = m_quickRedirectComing || m_policyLoadType == FrameLoadTypeRedirectWithLockedBackForwardList;
3786     m_quickRedirectComing = false;
3787
3788     if (!shouldContinue)
3789         return;
3790
3791     KURL url = request.url();
3792     
3793     m_documentLoader->replaceRequestURLForAnchorScroll(url);
3794     if (!isRedirect && !shouldTreatURLAsSameAsCurrent(url)) {
3795         // NB: must happen after _setURL, since we add based on the current request.
3796         // Must also happen before we openURL and displace the scroll position, since
3797         // adding the BF item will save away scroll state.
3798         
3799         // NB2:  If we were loading a long, slow doc, and the user anchor nav'ed before
3800         // it was done, currItem is now set the that slow doc, and prevItem is whatever was
3801         // before it.  Adding the b/f item will bump the slow doc down to prevItem, even
3802         // though its load is not yet done.  I think this all works out OK, for one because
3803         // we have already saved away the scroll and doc state for the long slow load,
3804         // but it's not an obvious case.
3805
3806         addHistoryItemForFragmentScroll();
3807     }
3808     
3809     scrollToAnchor(url);
3810     
3811     if (!isRedirect)
3812         // This will clear previousItem from the rest of the frame tree that didn't
3813         // doing any loading. We need to make a pass on this now, since for anchor nav
3814         // we'll not go through a real load and reach Completed state.
3815         checkLoadComplete();
3816  
3817     m_client->dispatchDidChangeLocationWithinPage();
3818     m_client->didFinishLoad();
3819 }
3820
3821 bool FrameLoader::shouldScrollToAnchor(bool isFormSubmission, FrameLoadType loadType, const KURL& url)
3822 {
3823     // Should we do anchor navigation within the existing content?
3824
3825     // We don't do this if we are submitting a form, explicitly reloading,
3826     // currently displaying a frameset, or if the URL does not have a fragment.
3827     // These rules were originally based on what KHTML was doing in KHTMLPart::openURL.
3828
3829     // FIXME: What about load types other than Standard and Reload?
3830
3831     return !isFormSubmission
3832         && loadType != FrameLoadTypeReload
3833         && loadType != FrameLoadTypeReloadFromOrigin
3834         && loadType != FrameLoadTypeSame
3835         && !shouldReload(this->url(), url)
3836         // We don't want to just scroll if a link from within a
3837         // frameset is trying to reload the frameset into _top.
3838         && !m_frame->document()->isFrameSet();
3839 }
3840
3841 void FrameLoader::checkNewWindowPolicy(const NavigationAction& action, const ResourceRequest& request,
3842     PassRefPtr<FormState> formState, const String& frameName)
3843 {
3844     m_policyCheck.set(request, formState, frameName,
3845         callContinueLoadAfterNewWindowPolicy, this);
3846     m_client->dispatchDecidePolicyForNewWindowAction(&FrameLoader::continueAfterNewWindowPolicy,
3847         action, request, formState, frameName);
3848 }
3849
3850 void FrameLoader::continueAfterNewWindowPolicy(PolicyAction policy)
3851 {
3852     PolicyCheck check = m_policyCheck;
3853     m_policyCheck.clear();
3854
3855     switch (policy) {
3856         case PolicyIgnore:
3857             check.clearRequest();
3858             break;
3859         case PolicyDownload:
3860             m_client->startDownload(check.request());
3861             check.clearRequest();
3862             break;
3863         case PolicyUse:
3864             break;
3865     }
3866
3867     check.call(policy == PolicyUse);
3868 }
3869
3870 void FrameLoader::checkNavigationPolicy(const ResourceRequest& request, DocumentLoader* loader,
3871     PassRefPtr<FormState> formState, NavigationPolicyDecisionFunction function, void* argument)
3872 {
3873     NavigationAction action = loader->triggeringAction();
3874     if (action.isEmpty()) {
3875         action = NavigationAction(request.url(), NavigationTypeOther);
3876         loader->setTriggeringAction(action);
3877     }
3878         
3879     // Don't ask more than once for the same request or if we are loading an empty URL.
3880     // This avoids confusion on the part of the client.
3881     if (equalIgnoringHeaderFields(request, loader->lastCheckedRequest()) || (!request.isNull() && request.url().isEmpty())) {
3882         function(argument, request, 0, true);
3883         loader->setLastCheckedRequest(request);
3884         return;
3885     }
3886     
3887     // We are always willing to show alternate content for unreachable URLs;
3888     // treat it like a reload so it maintains the right state for b/f list.
3889     if (loader->substituteData().isValid() && !loader->substituteData().failingURL().isEmpty()) {
3890         if (isBackForwardLoadType(m_policyLoadType))
3891             m_policyLoadType = FrameLoadTypeReload;
3892         function(argument, request, 0, true);
3893         return;
3894     }
3895     
3896     loader->setLastCheckedRequest(request);
3897
3898     m_policyCheck.set(request, formState.get(), function, argument);
3899
3900     m_delegateIsDecidingNavigationPolicy = true;
3901     m_client->dispatchDecidePolicyForNavigationAction(&FrameLoader::continueAfterNavigationPolicy,
3902         action, request, formState);
3903     m_delegateIsDecidingNavigationPolicy = false;
3904 }
3905
3906 void FrameLoader::continueAfterNavigationPolicy(PolicyAction policy)
3907 {
3908     PolicyCheck check = m_policyCheck;
3909     m_policyCheck.clear();
3910
3911     bool shouldContinue = policy == PolicyUse;
3912     
3913     switch (policy) {
3914         case PolicyIgnore:
3915             check.clearRequest();
3916             break;
3917         case PolicyDownload:
3918             m_client->startDownload(check.request());
3919             check.clearRequest();
3920             break;
3921         case PolicyUse: {
3922             ResourceRequest request(check.request());
3923             
3924             if (!m_client->canHandleRequest(request)) {
3925                 handleUnimplementablePolicy(m_client->cannotShowURLError(check.request()));
3926                 check.clearRequest();
3927                 shouldContinue = false;
3928             }
3929             break;
3930         }
3931     }
3932
3933     check.call(shouldContinue);
3934 }
3935
3936 void FrameLoader::callContinueLoadAfterNavigationPolicy(void* argument,
3937     const ResourceRequest& request, PassRefPtr<FormState> formState, bool shouldContinue)
3938 {
3939     FrameLoader* loader = static_cast<FrameLoader*>(argument);
3940     loader->continueLoadAfterNavigationPolicy(request, formState, shouldContinue);
3941 }
3942
3943 void FrameLoader::continueLoadAfterNavigationPolicy(const ResourceRequest&, PassRefPtr<FormState> formState, bool shouldContinue)
3944 {
3945     // If we loaded an alternate page to replace an unreachableURL, we'll get in here with a
3946     // nil policyDataSource because loading the alternate page will have passed
3947     // through this method already, nested; otherwise, policyDataSource should still be set.
3948     ASSERT(m_policyDocumentLoader || !m_provisionalDocumentLoader->unreachableURL().isEmpty());
3949
3950     bool isTargetItem = m_provisionalHistoryItem ? m_provisionalHistoryItem->isTargetItem() : false;
3951
3952     // Two reasons we can't continue:
3953     //    1) Navigation policy delegate said we can't so request is nil. A primary case of this 
3954     //       is the user responding Cancel to the form repost nag sheet.
3955     //    2) User responded Cancel to an alert popped up by the before unload event handler.
3956     // The "before unload" event handler runs only for the main frame.
3957     bool canContinue = shouldContinue && (!isLoadingMainFrame() || m_frame->shouldClose());
3958
3959     if (!canContinue) {
3960         // If we were waiting for a quick redirect, but the policy delegate decided to ignore it, then we 
3961         // need to report that the client redirect was cancelled.
3962         if (m_quickRedirectComing)
3963             clientRedirectCancelledOrFinished(false);
3964
3965         setPolicyDocumentLoader(0);
3966
3967         // If the navigation request came from the back/forward menu, and we punt on it, we have the 
3968         // problem that we have optimistically moved the b/f cursor already, so move it back.  For sanity, 
3969         // we only do this when punting a navigation for the target frame or top-level frame.  
3970         if ((isTargetItem || isLoadingMainFrame()) && isBackForwardLoadType(m_policyLoadType))
3971             if (Page* page = m_frame->page()) {
3972                 Frame* mainFrame = page->mainFrame();
3973                 if (HistoryItem* resetItem = mainFrame->loader()->m_currentHistoryItem.get()) {
3974                     page->backForwardList()->goToItem(resetItem);
3975                     Settings* settings = m_frame->settings();
3976                     page->setGlobalHistoryItem((!settings || settings->privateBrowsingEnabled()) ? 0 : resetItem);
3977                 }
3978             }
3979         return;
3980     }
3981
3982     FrameLoadType type = m_policyLoadType;
3983     stopAllLoaders();
3984     
3985     // <rdar://problem/6250856> - In certain circumstances on pages with multiple frames, stopAllLoaders()
3986     // might detach the current FrameLoader, in which case we should bail on this newly defunct load. 
3987     if (!m_frame->page())
3988         return;
3989         
3990     setProvisionalDocumentLoader(m_policyDocumentLoader.get());
3991     m_loadType = type;
3992     setState(FrameStateProvisional);
3993
3994     setPolicyDocumentLoader(0);
3995
3996     if (isBackForwardLoadType(type) && loadProvisionalItemFromCachedPage())
3997         return;
3998
3999     if (formState)
4000         m_client->dispatchWillSubmitForm(&FrameLoader::continueLoadAfterWillSubmitForm, formState);
4001     else
4002         continueLoadAfterWillSubmitForm();
4003 }
4004
4005
4006 void FrameLoader::callContinueLoadAfterNewWindowPolicy(void* argument,
4007     const ResourceRequest& request, PassRefPtr<FormState> formState, const String& frameName, bool shouldContinue)
4008 {
4009     FrameLoader* loader = static_cast<FrameLoader*>(argument);
4010     loader->continueLoadAfterNewWindowPolicy(request, formState, frameName, shouldContinue);
4011 }
4012
4013 void FrameLoader::continueLoadAfterNewWindowPolicy(const ResourceRequest& request,
4014     PassRefPtr<FormState> formState, const String& frameName, bool shouldContinue)
4015 {
4016     if (!shouldContinue)
4017         return;
4018
4019     RefPtr<Frame> frame = m_frame;
4020     RefPtr<Frame> mainFrame = m_client->dispatchCreatePage();
4021     if (!mainFrame)
4022         return;
4023
4024     if (frameName != "_blank")
4025         mainFrame->tree()->setName(frameName);
4026
4027     mainFrame->loader()->setOpenedByDOM();
4028     mainFrame->loader()->m_client->dispatchShow();
4029     mainFrame->loader()->setOpener(frame.get());
4030     mainFrame->loader()->loadWithNavigationAction(request, NavigationAction(), false, FrameLoadTypeStandard, formState);
4031 }
4032
4033 void FrameLoader::sendRemainingDelegateMessages(unsigned long identifier, const ResourceResponse& response, int length, const ResourceError& error)
4034 {    
4035     if (!response.isNull())
4036         dispatchDidReceiveResponse(m_documentLoader.get(), identifier, response);
4037     
4038     if (length > 0)
4039         dispatchDidReceiveContentLength(m_documentLoader.get(), identifier, length);
4040     
4041     if (error.isNull())
4042         dispatchDidFinishLoading(m_documentLoader.get(), identifier);
4043     else
4044         m_client->dispatchDidFailLoading(m_documentLoader.get(), identifier, error);
4045 }
4046
4047 void FrameLoader::requestFromDelegate(ResourceRequest& request, unsigned long& identifier, ResourceError& error)
4048 {
4049     ASSERT(!request.isNull());
4050
4051     identifier = 0;
4052     if (Page* page = m_frame->page()) {
4053         identifier = page->progress()->createUniqueIdentifier();
4054         dispatchAssignIdentifierToInitialRequest(identifier, m_documentLoader.get(), request);
4055     }
4056
4057     ResourceRequest newRequest(request);
4058     dispatchWillSendRequest(m_documentLoader.get(), identifier, newRequest, ResourceResponse());
4059
4060     if (newRequest.isNull())
4061         error = cancelledError(request);
4062     else
4063         error = ResourceError();
4064
4065     request = newRequest;
4066 }
4067
4068 void FrameLoader::loadedResourceFromMemoryCache(const CachedResource* resource)
4069 {
4070     Page* page = m_frame->page();
4071     if (!page)
4072         return;
4073
4074     page->inspectorController()->didLoadResourceFromMemoryCache(m_documentLoader.get(), resource);
4075
4076     if (!resource->sendResourceLoadCallbacks() || m_documentLoader->haveToldClientAboutLoad(resource->url()))
4077         return;
4078
4079     if (!page->areMemoryCacheClientCallsEnabled()) {
4080         m_documentLoader->recordMemoryCacheLoadForFutureClientNotification(resource->url());
4081         m_documentLoader->didTellClientAboutLoad(resource->url());
4082         return;
4083     }
4084
4085     ResourceRequest request(resource->url());
4086     if (m_client->dispatchDidLoadResourceFromMemoryCache(m_documentLoader.get(), request, resource->response(), resource->encodedSize())) {
4087         m_documentLoader->didTellClientAboutLoad(resource->url());
4088         return;
4089     }
4090
4091     unsigned long identifier;
4092     ResourceError error;
4093     requestFromDelegate(request, identifier, error);
4094     sendRemainingDelegateMessages(identifier, resource->response(), resource->encodedSize(), error);
4095 }
4096
4097 void FrameLoader::applyUserAgent(ResourceRequest& request)
4098 {
4099     String userAgent = client()->userAgent(request.url());
4100     ASSERT(!userAgent.isNull());
4101     request.setHTTPUserAgent(userAgent);
4102 }
4103
4104 bool FrameLoader::canGoBackOrForward(int distance) const
4105 {
4106     if (Page* page = m_frame->page()) {
4107         if (distance == 0)
4108             return true;
4109         if (distance > 0 && distance <= page->backForwardList()->forwardListCount())
4110             return true;
4111         if (distance < 0 && -distance <= page->backForwardList()->backListCount())
4112             return true;
4113     }
4114     return false;
4115 }
4116
4117 int FrameLoader::getHistoryLength()
4118 {
4119     if (Page* page = m_frame->page())
4120         return page->backForwardList()->backListCount() + 1;
4121     return 0;
4122 }
4123
4124 KURL FrameLoader::historyURL(int distance)
4125 {
4126     if (Page* page = m_frame->page()) {
4127         BackForwardList* list = page->backForwardList();
4128         HistoryItem* item = list->itemAtIndex(distance);
4129         if (!item) {
4130             if (distance > 0) {
4131                 int forwardListCount = list->forwardListCount();
4132                 if (forwardListCount > 0)
4133                     item = list->itemAtIndex(forwardListCount);
4134             } else {
4135                 int backListCount = list->backListCount();
4136                 if (backListCount > 0)
4137                     item = list->itemAtIndex(-backListCount);
4138             }
4139         }
4140         if (item)
4141             return item->url();
4142     }
4143     return KURL();
4144 }
4145
4146 void FrameLoader::addHistoryItemForFragmentScroll()
4147 {
4148     addBackForwardItemClippedAtTarget(false);
4149 }
4150
4151 bool FrameLoader::loadProvisionalItemFromCachedPage()
4152 {
4153     RefPtr<CachedPage> cachedPage = pageCache()->get(m_provisionalHistoryItem.get());
4154     if (!cachedPage || !cachedPage->document())
4155         return false;
4156     provisionalDocumentLoader()->loadFromCachedPage(cachedPage.release());
4157     return true;
4158 }
4159
4160 void FrameLoader::cachePageForHistoryItem(HistoryItem* item)
4161 {
4162     if (!canCachePage() || item->isInPageCache())
4163         return;
4164
4165     if (Page* page = m_frame->page()) {
4166         RefPtr<CachedPage> cachedPage = CachedPage::create(page);
4167         pageCache()->add(item, cachedPage.release());
4168     }
4169 }
4170
4171 bool FrameLoader::shouldTreatURLAsSameAsCurrent(const KURL& url) const
4172 {
4173     if (!m_currentHistoryItem)
4174         return false;
4175     return url == m_currentHistoryItem->url() || url == m_currentHistoryItem->originalURL();
4176 }
4177
4178 PassRefPtr<HistoryItem> FrameLoader::createHistoryItem(bool useOriginal)
4179 {
4180     DocumentLoader* docLoader = documentLoader();
4181     
4182     KURL unreachableURL = docLoader ? docLoader->unreachableURL() : KURL();
4183     
4184     KURL url;
4185     KURL originalURL;
4186
4187     if (!unreachableURL.isEmpty()) {
4188         url = unreachableURL;
4189         originalURL = unreachableURL;
4190     } else {
4191         originalURL = docLoader ? docLoader->originalURL() : KURL();
4192         if (useOriginal)
4193             url = originalURL;
4194         else if (docLoader)
4195             url = docLoader->requestURL();
4196     }
4197
4198     LOG(History, "WebCoreHistory: Creating item for %s", url.string().ascii().data());
4199     
4200     // Frames that have never successfully loaded any content
4201     // may have no URL at all. Currently our history code can't
4202     // deal with such things, so we nip that in the bud here.
4203     // Later we may want to learn to live with nil for URL.
4204     // See bug 3368236 and related bugs for more information.
4205     if (url.isEmpty()) 
4206         url = blankURL();
4207     if (originalURL.isEmpty())
4208         originalURL = blankURL();
4209     
4210     Frame* parentFrame = m_frame->tree()->parent();
4211     String parent = parentFrame ? parentFrame->tree()->name() : "";
4212     String title = docLoader ? docLoader->title() : "";
4213
4214     RefPtr<HistoryItem> item = HistoryItem::create(url, m_frame->tree()->name(), parent, title);
4215     item->setOriginalURLString(originalURL.string());
4216
4217     if (!unreachableURL.isEmpty() || !docLoader || docLoader->response().httpStatusCode() >= 400)
4218         item->setLastVisitWasFailure(true);
4219
4220     // Save form state if this is a POST