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