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