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