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