1c2a1ea54a9825a2e63e729a473fc8e7e28be2e4
[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     // This function prevents these exploits:
2312     // <rdar://problem/3715785> multiple frame injection vulnerability reported by Secunia, affects almost all browsers
2313     // http://bugs.webkit.org/show_bug.cgi?id=15936 Overly permissive frame navigation allows password theft
2314
2315     // Allow if there is no specific target.
2316     if (!targetFrame)
2317         return true;
2318     if (m_frame == targetFrame)
2319         return true;
2320
2321     // The navigation change is safe if the active frame is:
2322     //   - in the same security domain (satisfies same-origin policy)
2323     //   - the opener frame
2324     //   - an ancestor or a descendant in frame tree hierarchy
2325
2326     // Same security domain case.
2327     Document* activeDocument = m_frame->document();
2328     ASSERT(activeDocument);
2329     Document* targetDocument = targetFrame->document();
2330     if (!targetDocument)
2331         return true;
2332     const SecurityOrigin& activeSecurityOrigin = activeDocument->securityOrigin();
2333     const SecurityOrigin& targetSecurityOrigin = targetDocument->securityOrigin();
2334     if (activeSecurityOrigin.canAccess(targetSecurityOrigin))
2335         return true;
2336
2337     // Opener case.
2338     if (m_frame == targetFrame->loader()->opener())
2339         return true;
2340
2341     // Ancestor or descendant case.
2342     if (targetFrame->tree()->isDescendantOf(m_frame) || m_frame->tree()->isDescendantOf(targetFrame))
2343         return true;
2344
2345     if (!targetFrame->settings()->privateBrowsingEnabled()) {
2346         // FIXME: this error message should contain more specifics of why the navigation change is not allowed.
2347         String message = String::format("Unsafe JavaScript attempt to initiate a navigation change for frame with URL %s from frame with URL %s.\n",
2348                                         targetDocument->URL().utf8().data(), activeDocument->URL().utf8().data());
2349
2350         if (KJS::Interpreter::shouldPrintExceptions())
2351             printf("%s", message.utf8().data());
2352
2353         // FIXME: should we print to the console of the activeFrame as well?
2354         if (Page* page = targetFrame->page())
2355             page->chrome()->addMessageToConsole(JSMessageSource, ErrorMessageLevel, message, 1, String());
2356     }
2357     
2358     return false;
2359 }
2360
2361 void FrameLoader::stopLoadingSubframes()
2362 {
2363     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
2364         child->loader()->stopAllLoaders();
2365 }
2366
2367 void FrameLoader::stopAllLoaders()
2368 {
2369     // If this method is called from within this method, infinite recursion can occur (3442218). Avoid this.
2370     if (m_inStopAllLoaders)
2371         return;
2372
2373     m_inStopAllLoaders = true;
2374
2375     stopPolicyCheck();
2376
2377     stopLoadingSubframes();
2378     if (m_provisionalDocumentLoader)
2379         m_provisionalDocumentLoader->stopLoading();
2380     if (m_documentLoader)
2381         m_documentLoader->stopLoading();
2382     setProvisionalDocumentLoader(0);
2383     m_client->clearArchivedResources();
2384
2385     m_inStopAllLoaders = false;    
2386 }
2387
2388 void FrameLoader::stopForUserCancel(bool deferCheckLoadComplete)
2389 {
2390     stopAllLoaders();
2391     
2392     if (deferCheckLoadComplete)
2393         scheduleCheckLoadComplete();
2394     else if (m_frame->page())
2395         checkLoadComplete();
2396 }
2397
2398 void FrameLoader::cancelPendingArchiveLoad(ResourceLoader* loader)
2399 {
2400     m_client->cancelPendingArchiveLoad(loader);
2401 }
2402
2403 DocumentLoader* FrameLoader::activeDocumentLoader() const
2404 {
2405     if (m_state == FrameStateProvisional)
2406         return m_provisionalDocumentLoader.get();
2407     return m_documentLoader.get();
2408 }
2409
2410 bool FrameLoader::isLoading() const
2411 {
2412     DocumentLoader* docLoader = activeDocumentLoader();
2413     if (!docLoader)
2414         return false;
2415     return docLoader->isLoadingMainResource() || docLoader->isLoadingSubresources() || docLoader->isLoadingPlugIns();
2416 }
2417
2418 bool FrameLoader::frameHasLoaded() const
2419 {
2420     return m_committedFirstRealDocumentLoad || (m_provisionalDocumentLoader && !m_creatingInitialEmptyDocument); 
2421 }
2422
2423 void FrameLoader::setDocumentLoader(DocumentLoader* loader)
2424 {
2425     if (!loader && !m_documentLoader)
2426         return;
2427     
2428     ASSERT(loader != m_documentLoader);
2429     ASSERT(!loader || loader->frameLoader() == this);
2430
2431     m_client->prepareForDataSourceReplacement();
2432     detachChildren();
2433     if (m_documentLoader)
2434         m_documentLoader->detachFromFrame();
2435
2436     m_documentLoader = loader;
2437 }
2438
2439 DocumentLoader* FrameLoader::documentLoader() const
2440 {
2441     return m_documentLoader.get();
2442 }
2443
2444 void FrameLoader::setPolicyDocumentLoader(DocumentLoader* loader)
2445 {
2446     if (m_policyDocumentLoader == loader)
2447         return;
2448
2449     ASSERT(m_frame);
2450     if (loader)
2451         loader->setFrame(m_frame);
2452     if (m_policyDocumentLoader
2453             && m_policyDocumentLoader != m_provisionalDocumentLoader
2454             && m_policyDocumentLoader != m_documentLoader)
2455         m_policyDocumentLoader->detachFromFrame();
2456
2457     m_policyDocumentLoader = loader;
2458 }
2459    
2460 DocumentLoader* FrameLoader::provisionalDocumentLoader()
2461 {
2462     return m_provisionalDocumentLoader.get();
2463 }
2464
2465 void FrameLoader::setProvisionalDocumentLoader(DocumentLoader* loader)
2466 {
2467     ASSERT(!loader || !m_provisionalDocumentLoader);
2468     ASSERT(!loader || loader->frameLoader() == this);
2469
2470     if (m_provisionalDocumentLoader && m_provisionalDocumentLoader != m_documentLoader)
2471         m_provisionalDocumentLoader->detachFromFrame();
2472
2473     m_provisionalDocumentLoader = loader;
2474 }
2475
2476 FrameState FrameLoader::state() const
2477 {
2478     return m_state;
2479 }
2480
2481 double FrameLoader::timeOfLastCompletedLoad()
2482 {
2483     return storedTimeOfLastCompletedLoad;
2484 }
2485
2486 void FrameLoader::setState(FrameState newState)
2487 {    
2488     m_state = newState;
2489     
2490     if (newState == FrameStateProvisional)
2491         provisionalLoadStarted();
2492     else if (newState == FrameStateComplete) {
2493         frameLoadCompleted();
2494         storedTimeOfLastCompletedLoad = currentTime();
2495         if (m_documentLoader)
2496             m_documentLoader->stopRecordingResponses();
2497     }
2498 }
2499
2500 void FrameLoader::clearProvisionalLoad()
2501 {
2502     setProvisionalDocumentLoader(0);
2503     if (Page* page = m_frame->page())
2504         page->progress()->progressCompleted(m_frame);
2505     setState(FrameStateComplete);
2506 }
2507
2508 void FrameLoader::markLoadComplete()
2509 {
2510     setState(FrameStateComplete);
2511 }
2512
2513 void FrameLoader::commitProvisionalLoad(PassRefPtr<CachedPage> prpCachedPage)
2514 {
2515     RefPtr<CachedPage> cachedPage = prpCachedPage;
2516     RefPtr<DocumentLoader> pdl = m_provisionalDocumentLoader;
2517     
2518     if (m_loadType != FrameLoadTypeReplace)
2519         closeOldDataSources();
2520     
2521     if (!cachedPage && !m_creatingInitialEmptyDocument)
2522         m_client->makeRepresentation(pdl.get());
2523     
2524     transitionToCommitted(cachedPage);
2525     
2526     // Call clientRedirectCancelledOrFinished() here so that the frame load delegate is notified that the redirect's
2527     // status has changed, if there was a redirect.  The frame load delegate may have saved some state about
2528     // the redirect in its -webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:.  Since we are
2529     // just about to commit a new page, there cannot possibly be a pending redirect at this point.
2530     if (m_sentRedirectNotification)
2531         clientRedirectCancelledOrFinished(false);
2532     
2533     if (cachedPage && cachedPage->document()) {
2534         open(*cachedPage);
2535         cachedPage->clear();
2536     } else {        
2537         KURL url = pdl->substituteData().responseURL();
2538         if (url.isEmpty())
2539             url = pdl->URL();
2540         if (url.isEmpty())
2541             url = pdl->responseURL();
2542         if (url.isEmpty())
2543             url = "about:blank";
2544
2545         didOpenURL(url);
2546     }
2547     opened();
2548 }
2549
2550 void FrameLoader::transitionToCommitted(PassRefPtr<CachedPage> cachedPage)
2551 {
2552     ASSERT(m_client->hasWebView());
2553     ASSERT(m_state == FrameStateProvisional);
2554
2555     if (m_state != FrameStateProvisional)
2556         return;
2557
2558     m_client->setCopiesOnScroll();
2559     updateHistoryForCommit();
2560
2561     // The call to closeURL() invokes the unload event handler, which can execute arbitrary
2562     // JavaScript. If the script initiates a new load, we need to abandon the current load,
2563     // or the two will stomp each other.
2564     DocumentLoader* pdl = m_provisionalDocumentLoader.get();
2565     if (m_documentLoader)
2566         closeURL();
2567     if (pdl != m_provisionalDocumentLoader)
2568         return;
2569
2570     // Nothing else can interupt this commit - set the Provisional->Committed transition in stone
2571     if (m_documentLoader)
2572         m_documentLoader->stopLoadingSubresources();
2573     if (m_documentLoader)
2574         m_documentLoader->stopLoadingPlugIns();
2575
2576     setDocumentLoader(m_provisionalDocumentLoader.get());
2577     setProvisionalDocumentLoader(0);
2578     setState(FrameStateCommittedPage);
2579
2580     // Handle adding the URL to the back/forward list.
2581     DocumentLoader* dl = m_documentLoader.get();
2582     String ptitle = dl->title(); 
2583
2584     switch (m_loadType) {
2585         case FrameLoadTypeForward:
2586         case FrameLoadTypeBack:
2587         case FrameLoadTypeIndexedBackForward:
2588             if (Page* page = m_frame->page())
2589                 if (page->backForwardList()) {
2590                     updateHistoryForBackForwardNavigation();
2591
2592                     // Create a document view for this document, or used the cached view.
2593                     if (cachedPage)
2594                         m_client->setDocumentViewFromCachedPage(cachedPage.get());
2595                     else
2596                         m_client->makeDocumentView();
2597                 }
2598             break;
2599
2600         case FrameLoadTypeReload:
2601         case FrameLoadTypeSame:
2602         case FrameLoadTypeReplace:
2603             updateHistoryForReload();
2604             m_client->makeDocumentView();
2605             break;
2606
2607         // FIXME - just get rid of this case, and merge FrameLoadTypeReloadAllowingStaleData with the above case
2608         case FrameLoadTypeReloadAllowingStaleData:
2609             m_client->makeDocumentView();
2610             break;
2611
2612         case FrameLoadTypeStandard:
2613             updateHistoryForStandardLoad();
2614 #ifndef BUILDING_ON_TIGER
2615             // This code was originally added for a Leopard performance imporvement. We decided to 
2616             // ifdef it to fix correctness issues on Tiger documented in <rdar://problem/5441823>.
2617             if (m_frame->view())
2618                 m_frame->view()->suppressScrollbars(true);
2619 #endif
2620             m_client->makeDocumentView();
2621             break;
2622
2623         case FrameLoadTypeRedirectWithLockedHistory:
2624             updateHistoryForRedirectWithLockedHistory();
2625             m_client->makeDocumentView();
2626             break;
2627
2628         // FIXME Remove this check when dummy ds is removed (whatever "dummy ds" is).
2629         // An exception should be thrown if we're in the FrameLoadTypeUninitialized state.
2630         default:
2631             ASSERT_NOT_REACHED();
2632     }
2633
2634     m_responseMIMEType = dl->responseMIMEType();
2635
2636     // Tell the client we've committed this URL.
2637     ASSERT(m_client->hasFrameView());
2638
2639     if (m_creatingInitialEmptyDocument)
2640         return;
2641
2642     m_committedFirstRealDocumentLoad = true;
2643     
2644     // For non-cached HTML pages, these methods are called in FrameLoader::begin.
2645     if (cachedPage || !m_client->hasHTMLView()) {
2646         dispatchDidCommitLoad(); 
2647             
2648         // If we have a title let the WebView know about it. 
2649         if (!ptitle.isNull()) 
2650             m_client->dispatchDidReceiveTitle(ptitle);         
2651     }
2652 }
2653
2654 bool FrameLoader::privateBrowsingEnabled() const
2655 {
2656     return m_client->privateBrowsingEnabled();
2657 }
2658
2659 void FrameLoader::clientRedirectCancelledOrFinished(bool cancelWithLoadInProgress)
2660 {
2661     // Note that -webView:didCancelClientRedirectForFrame: is called on the frame load delegate even if
2662     // the redirect succeeded.  We should either rename this API, or add a new method, like
2663     // -webView:didFinishClientRedirectForFrame:
2664     m_client->dispatchDidCancelClientRedirect();
2665
2666     if (!cancelWithLoadInProgress)
2667         m_quickRedirectComing = false;
2668
2669     m_sentRedirectNotification = false;
2670 }
2671
2672 void FrameLoader::clientRedirected(const KURL& URL, double seconds, double fireDate, bool lockHistory, bool isJavaScriptFormAction)
2673 {
2674     m_client->dispatchWillPerformClientRedirect(URL, seconds, fireDate);
2675     
2676     // Remember that we sent a redirect notification to the frame load delegate so that when we commit
2677     // the next provisional load, we can send a corresponding -webView:didCancelClientRedirectForFrame:
2678     m_sentRedirectNotification = true;
2679     
2680     // If a "quick" redirect comes in an, we set a special mode so we treat the next
2681     // load as part of the same navigation. If we don't have a document loader, we have
2682     // no "original" load on which to base a redirect, so we treat the redirect as a normal load.
2683     m_quickRedirectComing = lockHistory && m_documentLoader && !isJavaScriptFormAction;
2684 }
2685
2686 bool FrameLoader::shouldReload(const KURL& currentURL, const KURL& destinationURL)
2687 {
2688     // This function implements the rule: "Don't reload if navigating by fragment within
2689     // the same URL, but do reload if going to a new URL or to the same URL with no
2690     // fragment identifier at all."
2691     if (!currentURL.hasRef() && !destinationURL.hasRef())
2692         return true;
2693     return !equalIgnoringRef(currentURL, destinationURL);
2694 }
2695
2696 void FrameLoader::closeOldDataSources()
2697 {
2698     // FIXME: Is it important for this traversal to be postorder instead of preorder?
2699     // If so, add helpers for postorder traversal, and use them. If not, then lets not
2700     // use a recursive algorithm here.
2701     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
2702         child->loader()->closeOldDataSources();
2703     
2704     if (m_documentLoader)
2705         m_client->dispatchWillClose();
2706
2707     m_client->setMainFrameDocumentReady(false); // stop giving out the actual DOMDocument to observers
2708 }
2709
2710 void FrameLoader::open(CachedPage& cachedPage)
2711 {
2712     ASSERT(m_frame->page());
2713     ASSERT(m_frame->page()->mainFrame() == m_frame);
2714
2715     cancelRedirection();
2716
2717     // We still have to close the previous part page.
2718     closeURL();
2719
2720     m_isComplete = false;
2721     
2722     // Don't re-emit the load event.
2723     m_didCallImplicitClose = true;
2724     
2725     // Delete old status bar messages (if it _was_ activated on last URL).
2726     Settings* settings = m_frame->settings();
2727     if (settings && settings->isJavaScriptEnabled()) {
2728         m_frame->setJSStatusBarText(String());
2729         m_frame->setJSDefaultStatusBarText(String());
2730     }
2731
2732     KURL URL = cachedPage.URL();
2733
2734     if (URL.protocol().startsWith("http") && !URL.host().isEmpty() && URL.path().isEmpty())
2735         URL.setPath("/");
2736     
2737     m_URL = URL;
2738     m_workingURL = URL;
2739
2740     started();
2741
2742     clear();
2743
2744     Document* document = cachedPage.document();
2745     ASSERT(document);
2746     document->setInPageCache(false);
2747
2748     m_needsClear = true;
2749     m_isComplete = false;
2750     m_didCallImplicitClose = false;
2751     m_outgoingReferrer = URL.url();
2752
2753     FrameView* view = cachedPage.view();
2754     if (view)
2755         view->setWasScrolledByUser(false);
2756     m_frame->setView(view);
2757     
2758     m_frame->setDocument(document);
2759     m_decoder = document->decoder();
2760
2761     updatePolicyBaseURL();
2762
2763     cachedPage.restore(m_frame->page());
2764
2765     checkCompleted();
2766 }
2767
2768 bool FrameLoader::isStopping() const
2769 {
2770     return activeDocumentLoader()->isStopping();
2771 }
2772
2773 void FrameLoader::finishedLoading()
2774 {
2775     // Retain because the stop may release the last reference to it.
2776     RefPtr<Frame> protect(m_frame);
2777
2778     RefPtr<DocumentLoader> dl = activeDocumentLoader();
2779     dl->finishedLoading();
2780     if (!dl->mainDocumentError().isNull() || !dl->frameLoader())
2781         return;
2782     dl->setPrimaryLoadComplete(true);
2783     m_client->dispatchDidLoadMainResource(dl.get());
2784     checkLoadComplete();
2785 }
2786
2787 // FIXME: Which one of these URL methods is right?
2788
2789 KURL FrameLoader::url() const
2790 {
2791     return m_URL;
2792 }
2793
2794 KURL FrameLoader::URL() const
2795 {
2796     return activeDocumentLoader()->URL();
2797 }
2798
2799 bool FrameLoader::isArchiveLoadPending(ResourceLoader* loader) const
2800 {
2801     return m_client->isArchiveLoadPending(loader);
2802 }
2803
2804 bool FrameLoader::isHostedByObjectElement() const
2805 {
2806     HTMLFrameOwnerElement* owner = m_frame->ownerElement();
2807     return owner && owner->hasTagName(objectTag);
2808 }
2809
2810 bool FrameLoader::isLoadingMainFrame() const
2811 {
2812     Page* page = m_frame->page();
2813     return page && m_frame == page->mainFrame();
2814 }
2815
2816 bool FrameLoader::canShowMIMEType(const String& MIMEType) const
2817 {
2818     return m_client->canShowMIMEType(MIMEType);
2819 }
2820
2821 bool FrameLoader::representationExistsForURLScheme(const String& URLScheme)
2822 {
2823     return m_client->representationExistsForURLScheme(URLScheme);
2824 }
2825
2826 String FrameLoader::generatedMIMETypeForURLScheme(const String& URLScheme)
2827 {
2828     return m_client->generatedMIMETypeForURLScheme(URLScheme);
2829 }
2830
2831 void FrameLoader::cancelContentPolicyCheck()
2832 {
2833     m_client->cancelPolicyCheck();
2834     m_policyCheck.clear();
2835 }
2836
2837 void FrameLoader::didReceiveServerRedirectForProvisionalLoadForFrame()
2838 {
2839     m_client->dispatchDidReceiveServerRedirectForProvisionalLoad();
2840 }
2841
2842 void FrameLoader::finishedLoadingDocument(DocumentLoader* loader)
2843 {
2844 #if PLATFORM(WIN)
2845     if (!m_creatingInitialEmptyDocument)
2846 #endif
2847         m_client->finishedLoading(loader);
2848 }
2849
2850 bool FrameLoader::isReplacing() const
2851 {
2852     return m_loadType == FrameLoadTypeReplace;
2853 }
2854
2855 void FrameLoader::setReplacing()
2856 {
2857     m_loadType = FrameLoadTypeReplace;
2858 }
2859
2860 void FrameLoader::revertToProvisional(DocumentLoader* loader)
2861 {
2862     m_client->revertToProvisionalState(loader);
2863 }
2864
2865 bool FrameLoader::subframeIsLoading() const
2866 {
2867     // It's most likely that the last added frame is the last to load so we walk backwards.
2868     for (Frame* child = m_frame->tree()->lastChild(); child; child = child->tree()->previousSibling()) {
2869         FrameLoader* childLoader = child->loader();
2870         DocumentLoader* documentLoader = childLoader->documentLoader();
2871         if (documentLoader && documentLoader->isLoadingInAPISense())
2872             return true;
2873         documentLoader = childLoader->provisionalDocumentLoader();
2874         if (documentLoader && documentLoader->isLoadingInAPISense())
2875             return true;
2876     }
2877     return false;
2878 }
2879
2880 void FrameLoader::willChangeTitle(DocumentLoader* loader)
2881 {
2882     m_client->willChangeTitle(loader);
2883 }
2884
2885 FrameLoadType FrameLoader::loadType() const
2886 {
2887     return m_loadType;
2888 }
2889
2890 void FrameLoader::stopPolicyCheck()
2891 {
2892     m_client->cancelPolicyCheck();
2893     PolicyCheck check = m_policyCheck;
2894     m_policyCheck.clear();
2895     check.cancel();
2896 }
2897
2898 void FrameLoader::checkLoadCompleteForThisFrame()
2899 {
2900     ASSERT(m_client->hasWebView());
2901
2902     switch (m_state) {
2903         case FrameStateProvisional: {
2904             if (m_delegateIsHandlingProvisionalLoadError)
2905                 return;
2906
2907             RefPtr<DocumentLoader> pdl = m_provisionalDocumentLoader;
2908             if (!pdl)
2909                 return;
2910                 
2911             // If we've received any errors we may be stuck in the provisional state and actually complete.
2912             const ResourceError& error = pdl->mainDocumentError();
2913             if (error.isNull())
2914                 return;
2915
2916             // Check all children first.
2917             RefPtr<HistoryItem> item;
2918             if (Page* page = m_frame->page())
2919                 if (isBackForwardLoadType(loadType()) && m_frame == page->mainFrame())
2920                     item = m_currentHistoryItem;
2921                 
2922             bool shouldReset = true;
2923             if (!pdl->isLoadingInAPISense()) {
2924                 m_delegateIsHandlingProvisionalLoadError = true;
2925                 m_client->dispatchDidFailProvisionalLoad(error);
2926                 m_delegateIsHandlingProvisionalLoadError = false;
2927
2928                 // FIXME: can stopping loading here possibly have any effect, if isLoading is false,
2929                 // which it must be to be in this branch of the if? And is it OK to just do a full-on
2930                 // stopAllLoaders instead of stopLoadingSubframes?
2931                 stopLoadingSubframes();
2932                 pdl->stopLoading();
2933
2934                 // Finish resetting the load state, but only if another load hasn't been started by the
2935                 // delegate callback.
2936                 if (pdl == m_provisionalDocumentLoader)
2937                     clearProvisionalLoad();
2938                 else if (m_provisionalDocumentLoader) {
2939                     KURL unreachableURL = m_provisionalDocumentLoader->unreachableURL();
2940                     if (!unreachableURL.isEmpty() && unreachableURL == pdl->request().url())
2941                         shouldReset = false;
2942                 }
2943             }
2944             if (shouldReset && item)
2945                 if (Page* page = m_frame->page())
2946                     page->backForwardList()->goToItem(item.get());
2947             return;
2948         }
2949         
2950         case FrameStateCommittedPage: {
2951             DocumentLoader* dl = m_documentLoader.get();            
2952             if (!dl || dl->isLoadingInAPISense())
2953                 return;
2954
2955             markLoadComplete();
2956
2957             // FIXME: Is this subsequent work important if we already navigated away?
2958             // Maybe there are bugs because of that, or extra work we can skip because
2959             // the new page is ready.
2960
2961             m_client->forceLayoutForNonHTML();
2962              
2963             // If the user had a scroll point, scroll to it, overriding the anchor point if any.
2964             if (Page* page = m_frame->page())
2965                 if ((isBackForwardLoadType(m_loadType) || m_loadType == FrameLoadTypeReload) && page->backForwardList())
2966                     restoreScrollPositionAndViewState();
2967
2968             if (m_creatingInitialEmptyDocument || !m_committedFirstRealDocumentLoad)
2969                 return;
2970
2971             const ResourceError& error = dl->mainDocumentError();
2972             if (!error.isNull())
2973                 m_client->dispatchDidFailLoad(error);
2974             else
2975                 m_client->dispatchDidFinishLoad();
2976
2977             if (Page* page = m_frame->page())
2978                 page->progress()->progressCompleted(m_frame);
2979             return;
2980         }
2981         
2982         case FrameStateComplete:
2983             // Even if already complete, we might have set a previous item on a frame that
2984             // didn't do any data loading on the past transaction. Make sure to clear these out.
2985             m_client->frameLoadCompleted();
2986             return;
2987     }
2988
2989     ASSERT_NOT_REACHED();
2990 }
2991
2992 void FrameLoader::continueAfterContentPolicy(PolicyAction policy)
2993 {
2994     PolicyCheck check = m_policyCheck;
2995     m_policyCheck.clear();
2996     check.call(policy);
2997 }
2998
2999 void FrameLoader::continueLoadAfterWillSubmitForm(PolicyAction)
3000 {
3001     if (!m_provisionalDocumentLoader)
3002         return;
3003
3004     m_provisionalDocumentLoader->prepareForLoadStart();
3005
3006     DocumentLoader* activeDocLoader = activeDocumentLoader();
3007     if (activeDocLoader && activeDocLoader->isLoadingMainResource())
3008         return;
3009
3010     m_provisionalDocumentLoader->setLoadingFromCachedPage(false);
3011
3012     unsigned long identifier = 0;
3013
3014     if (Page* page = m_frame->page()) {
3015         identifier = page->progress()->createUniqueIdentifier();
3016         dispatchAssignIdentifierToInitialRequest(identifier, m_provisionalDocumentLoader.get(), m_provisionalDocumentLoader->originalRequest());
3017     }
3018
3019     if (!m_provisionalDocumentLoader->startLoadingMainResource(identifier))
3020         m_provisionalDocumentLoader->updateLoading();
3021 }
3022
3023 void FrameLoader::didFirstLayout()
3024 {
3025     if (Page* page = m_frame->page())
3026         if (isBackForwardLoadType(m_loadType) && page->backForwardList())
3027             restoreScrollPositionAndViewState();
3028
3029     m_firstLayoutDone = true;
3030     m_client->dispatchDidFirstLayout();
3031 }
3032
3033 void FrameLoader::frameLoadCompleted()
3034 {
3035     m_client->frameLoadCompleted();
3036
3037     // After a canceled provisional load, firstLayoutDone is false.
3038     // Reset it to true if we're displaying a page.
3039     if (m_documentLoader)
3040         m_firstLayoutDone = true;
3041 }
3042
3043 bool FrameLoader::firstLayoutDone() const
3044 {
3045     return m_firstLayoutDone;
3046 }
3047
3048 bool FrameLoader::isQuickRedirectComing() const
3049 {
3050     return m_quickRedirectComing;
3051 }
3052
3053 void FrameLoader::detachChildren()
3054 {
3055     // FIXME: Is it really necessary to do this in reverse order?
3056     Frame* previous;
3057     for (Frame* child = m_frame->tree()->lastChild(); child; child = previous) {
3058         previous = child->tree()->previousSibling();
3059         child->loader()->detachFromParent();
3060     }
3061 }
3062
3063 void FrameLoader::recursiveCheckLoadComplete()
3064 {
3065     Vector<RefPtr<Frame>, 10> frames;
3066     
3067     for (RefPtr<Frame> frame = m_frame->tree()->firstChild(); frame; frame = frame->tree()->nextSibling())
3068         frames.append(frame);
3069     
3070     unsigned size = frames.size();
3071     for (unsigned i = 0; i < size; i++)
3072         frames[i]->loader()->recursiveCheckLoadComplete();
3073     
3074     checkLoadCompleteForThisFrame();
3075 }
3076
3077 // Called every time a resource is completely loaded, or an error is received.
3078 void FrameLoader::checkLoadComplete()
3079 {
3080     ASSERT(m_client->hasWebView());
3081     
3082     // FIXME: Always traversing the entire frame tree is a bit inefficient, but 
3083     // is currently needed in order to null out the previous history item for all frames.
3084     if (Page* page = m_frame->page())
3085         page->mainFrame()->loader()->recursiveCheckLoadComplete();
3086 }
3087
3088 int FrameLoader::numPendingOrLoadingRequests(bool recurse) const
3089 {
3090     if (!recurse)
3091         return numRequests(m_frame->document());
3092
3093     int count = 0;
3094     for (Frame* frame = m_frame; frame; frame = frame->tree()->traverseNext(m_frame))
3095         count += numRequests(frame->document());
3096     return count;
3097 }
3098
3099 FrameLoaderClient* FrameLoader::client() const
3100 {
3101     return m_client;
3102 }
3103
3104 void FrameLoader::submitForm(const FrameLoadRequest& request, Event* event)
3105 {
3106     // FIXME: We'd like to remove this altogether and fix the multiple form submission issue another way.
3107     // We do not want to submit more than one form from the same page,
3108     // nor do we want to submit a single form more than once.
3109     // This flag prevents these from happening; not sure how other browsers prevent this.
3110     // The flag is reset in each time we start handle a new mouse or key down event, and
3111     // also in setView since this part may get reused for a page from the back/forward cache.
3112     // The form multi-submit logic here is only needed when we are submitting a form that affects this frame.
3113     // FIXME: Frame targeting is only one of the ways the submission could end up doing something other
3114     // than replacing this frame's content, so this check is flawed. On the other hand, the check is hardly
3115     // needed any more now that we reset m_submittedFormURL on each mouse or key down event.
3116     Frame* target = m_frame->tree()->find(request.frameName());
3117     if (m_frame->tree()->isDescendantOf(target)) {
3118         if (m_submittedFormURL == request.resourceRequest().url())
3119             return;
3120         m_submittedFormURL = request.resourceRequest().url();
3121     }
3122
3123     // FIXME: We should probably call userGestureHint() to tell whether this form submission was the result of a user gesture.
3124     load(request, false, true, event, m_formAboutToBeSubmitted.get(), m_formValuesAboutToBeSubmitted);
3125
3126     clearRecordedFormValues();
3127 }
3128
3129 void FrameLoader::urlSelected(const FrameLoadRequest& request, Event* event, bool lockHistory, bool userGesture)
3130 {
3131     FrameLoadRequest copy = request;
3132     if (copy.resourceRequest().httpReferrer().isEmpty())
3133         copy.resourceRequest().setHTTPReferrer(m_outgoingReferrer);
3134
3135     load(copy, lockHistory, userGesture, event, 0, HashMap<String, String>());
3136 }
3137     
3138 String FrameLoader::userAgent(const KURL& url) const
3139 {
3140     return m_client->userAgent(url);
3141 }
3142
3143 void FrameLoader::tokenizerProcessedData()
3144 {
3145     ASSERT(m_frame->page());
3146     ASSERT(m_frame->document());
3147
3148     checkCompleted();
3149 }
3150
3151 void FrameLoader::didTellBridgeAboutLoad(const String& URL)
3152 {
3153     m_urlsBridgeKnowsAbout.add(URL);
3154 }
3155
3156 bool FrameLoader::haveToldBridgeAboutLoad(const String& URL)
3157 {
3158     return m_urlsBridgeKnowsAbout.contains(URL);
3159 }
3160
3161 void FrameLoader::handledOnloadEvents()
3162 {
3163     m_client->dispatchDidHandleOnloadEvents();
3164 }
3165
3166 void FrameLoader::frameDetached()
3167 {
3168     stopAllLoaders();
3169     detachFromParent();
3170 }
3171
3172 void FrameLoader::detachFromParent()
3173 {
3174     RefPtr<Frame> protect(m_frame);
3175
3176     closeURL();
3177     stopAllLoaders();
3178     saveScrollPositionAndViewStateToItem(currentHistoryItem());
3179     detachChildren();
3180
3181     if (Page* page = m_frame->page())
3182         page->inspectorController()->frameDetachedFromParent(m_frame);
3183
3184     m_client->detachedFromParent2();
3185     setDocumentLoader(0);
3186     m_client->detachedFromParent3();
3187     if (Frame* parent = m_frame->tree()->parent()) {
3188         parent->tree()->removeChild(m_frame);
3189         parent->loader()->scheduleCheckCompleted();
3190     } else {
3191         m_frame->setView(0);
3192         m_frame->pageDestroyed();
3193     }
3194 #if PLATFORM(MAC)
3195     [m_frame->bridge() close];
3196 #endif
3197     m_client->detachedFromParent4();
3198 }
3199
3200 void FrameLoader::dispatchDidChangeLocationWithinPage()
3201 {
3202     m_client->dispatchDidChangeLocationWithinPage();
3203 }
3204
3205 void FrameLoader::dispatchDidFinishLoadToClient()
3206 {
3207     m_client->didFinishLoad();
3208 }
3209
3210 void FrameLoader::updateGlobalHistoryForStandardLoad(const KURL& url)
3211 {
3212     m_client->updateGlobalHistoryForStandardLoad(url);
3213 }
3214
3215 void FrameLoader::updateGlobalHistoryForReload(const KURL& url)
3216 {
3217     m_client->updateGlobalHistoryForReload(url);
3218 }
3219
3220 bool FrameLoader::shouldGoToHistoryItem(HistoryItem* item) const
3221 {
3222     return m_client->shouldGoToHistoryItem(item);
3223 }
3224
3225 void FrameLoader::addExtraFieldsToRequest(ResourceRequest& request, bool mainResource, bool alwaysFromRequest)
3226 {
3227     applyUserAgent(request);
3228     
3229     if (m_loadType == FrameLoadTypeReload) {
3230         request.setCachePolicy(ReloadIgnoringCacheData);
3231         request.setHTTPHeaderField("Cache-Control", "max-age=0");
3232     }
3233     
3234     // Don't set the cookie policy URL if it's already been set.
3235     if (request.mainDocumentURL().isEmpty()) {
3236         if (mainResource && (isLoadingMainFrame() || alwaysFromRequest))
3237             request.setMainDocumentURL(request.url());
3238         else if (Page* page = m_frame->page())
3239             request.setMainDocumentURL(page->mainFrame()->loader()->url());
3240     }
3241     
3242     if (mainResource)
3243         request.setHTTPAccept("text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5");
3244 }
3245
3246 void FrameLoader::committedLoad(DocumentLoader* loader, const char* data, int length)
3247 {
3248     m_client->committedLoad(loader, data, length);
3249 }
3250
3251 void FrameLoader::post(const KURL& URL, const String& referrer, const String& frameName, PassRefPtr<FormData> formData, 
3252     const String& contentType, Event* event, HTMLFormElement* form, const HashMap<String, String>& formValues)
3253 {
3254     // When posting, use the NSURLRequestReloadIgnoringCacheData load flag.
3255     // This prevents a potential bug which may cause a page with a form that uses itself
3256     // as an action to be returned from the cache without submitting.
3257
3258     // FIXME: Where's the code that implements what the comment above says?
3259
3260     ResourceRequest request(URL);
3261     addExtraFieldsToRequest(request, true, true);
3262
3263     if (!referrer.isEmpty())
3264         request.setHTTPReferrer(referrer);
3265     request.setHTTPMethod("POST");
3266     request.setHTTPBody(formData);
3267     request.setHTTPContentType(contentType);
3268
3269     NavigationAction action(URL, FrameLoadTypeStandard, true, event);
3270
3271     RefPtr<FormState> formState;
3272     if (form && !formValues.isEmpty())
3273         formState = FormState::create(form, formValues, m_frame);
3274
3275     if (!frameName.isEmpty()) {
3276         if (Frame* targetFrame = m_frame->tree()->find(frameName))
3277             targetFrame->loader()->load(request, action, FrameLoadTypeStandard, formState.release());
3278         else
3279             checkNewWindowPolicy(action, request, formState.release(), frameName);
3280     } else
3281         load(request, action, FrameLoadTypeStandard, formState.release());
3282 }
3283
3284 bool FrameLoader::isReloading() const
3285 {
3286     return documentLoader()->request().cachePolicy() == ReloadIgnoringCacheData;
3287 }
3288
3289 void FrameLoader::loadEmptyDocumentSynchronously()
3290 {
3291     ResourceRequest request(KURL(""));
3292     load(request);
3293 }
3294
3295 void FrameLoader::loadResourceSynchronously(const ResourceRequest& request, ResourceError& error, ResourceResponse& response, Vector<char>& data)
3296 {
3297     // Since this is a subresource, we can load any URL (we ignore the return value).
3298     // But we still want to know whether we should hide the referrer or not, so we call the canLoad method.
3299     String referrer = m_outgoingReferrer;
3300     if (shouldHideReferrer(request.url(), referrer))
3301         referrer = String();
3302     
3303     ResourceRequest initialRequest = request;
3304     initialRequest.setTimeoutInterval(10);
3305     
3306     if (initialRequest.isConditional())
3307         initialRequest.setCachePolicy(ReloadIgnoringCacheData);
3308     else
3309         initialRequest.setCachePolicy(documentLoader()->request().cachePolicy());
3310     
3311     if (!referrer.isEmpty())
3312         initialRequest.setHTTPReferrer(referrer);
3313
3314     if (Page* page = m_frame->page())
3315         initialRequest.setMainDocumentURL(page->mainFrame()->loader()->documentLoader()->request().url());
3316     initialRequest.setHTTPUserAgent(client()->userAgent(request.url()));
3317
3318     unsigned long identifier = 0;    
3319     ResourceRequest newRequest(initialRequest);
3320     requestFromDelegate(newRequest, identifier, error);
3321
3322     if (error.isNull()) {
3323         ASSERT(!newRequest.isNull());
3324         didTellBridgeAboutLoad(newRequest.url().url());
3325         ResourceHandle::loadResourceSynchronously(newRequest, error, response, data);
3326     }
3327     
3328     sendRemainingDelegateMessages(identifier, response, data.size(), error);
3329 }
3330
3331 void FrameLoader::assignIdentifierToInitialRequest(unsigned long identifier, const ResourceRequest& clientRequest)
3332 {
3333     return dispatchAssignIdentifierToInitialRequest(identifier, activeDocumentLoader(), clientRequest);
3334 }
3335
3336 void FrameLoader::willSendRequest(ResourceLoader* loader, ResourceRequest& clientRequest, const ResourceResponse& redirectResponse)
3337 {
3338     applyUserAgent(clientRequest);
3339     dispatchWillSendRequest(loader->documentLoader(), loader->identifier(), clientRequest, redirectResponse);
3340 }
3341
3342 void FrameLoader::didReceiveResponse(ResourceLoader* loader, const ResourceResponse& r)
3343 {
3344     activeDocumentLoader()->addResponse(r);
3345     
3346     if (Page* page = m_frame->page())
3347         page->progress()->incrementProgress(loader->identifier(), r);
3348     dispatchDidReceiveResponse(loader->documentLoader(), loader->identifier(), r);
3349 }
3350
3351 void FrameLoader::didReceiveData(ResourceLoader* loader, const char* data, int length, int lengthReceived)
3352 {
3353     if (Page* page = m_frame->page())
3354         page->progress()->incrementProgress(loader->identifier(), data, length);
3355     dispatchDidReceiveContentLength(loader->documentLoader(), loader->identifier(), lengthReceived);
3356 }
3357
3358 void FrameLoader::didFailToLoad(ResourceLoader* loader, const ResourceError& error)
3359 {
3360     if (Page* page = m_frame->page())
3361         page->progress()->completeProgress(loader->identifier());
3362     if (!error.isNull())
3363         m_client->dispatchDidFailLoading(loader->documentLoader(), loader->identifier(), error);
3364 }
3365
3366 const ResourceRequest& FrameLoader::originalRequest() const
3367 {
3368     return activeDocumentLoader()->originalRequestCopy();
3369 }
3370
3371 void FrameLoader::receivedMainResourceError(const ResourceError& error, bool isComplete)
3372 {
3373     // Retain because the stop may release the last reference to it.
3374     RefPtr<Frame> protect(m_frame);
3375
3376     RefPtr<DocumentLoader> loader = activeDocumentLoader();
3377     
3378     if (isComplete) {
3379         // FIXME: Don't want to do this if an entirely new load is going, so should check
3380         // that both data sources on the frame are either this or nil.
3381         stop();
3382         if (m_client->shouldFallBack(error))
3383             handleFallbackContent();
3384     }
3385     
3386     if (m_state == FrameStateProvisional && m_provisionalDocumentLoader) {
3387         KURL failedURL = m_provisionalDocumentLoader->originalRequestCopy().url();
3388         didNotOpenURL(failedURL);
3389             
3390         // We might have made a page cache item, but now we're bailing out due to an error before we ever
3391         // transitioned to the new page (before WebFrameState == commit).  The goal here is to restore any state
3392         // so that the existing view (that wenever got far enough to replace) can continue being used.
3393         invalidateCurrentItemCachedPage();
3394         
3395         // Call clientRedirectCancelledOrFinished here so that the frame load delegate is notified that the redirect's
3396         // status has changed, if there was a redirect. The frame load delegate may have saved some state about
3397         // the redirect in its -webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:. Since we are definitely
3398         // not going to use this provisional resource, as it was cancelled, notify the frame load delegate that the redirect
3399         // has ended.
3400         if (m_sentRedirectNotification)
3401             clientRedirectCancelledOrFinished(false);
3402     }
3403     
3404     
3405     loader->mainReceivedError(error, isComplete);
3406 }
3407
3408 void FrameLoader::callContinueFragmentScrollAfterNavigationPolicy(void* argument,
3409     const ResourceRequest& request, PassRefPtr<FormState>, bool shouldContinue)
3410 {
3411     FrameLoader* loader = static_cast<FrameLoader*>(argument);
3412     loader->continueFragmentScrollAfterNavigationPolicy(request, shouldContinue);
3413 }
3414
3415 void FrameLoader::continueFragmentScrollAfterNavigationPolicy(const ResourceRequest& request, bool shouldContinue)
3416 {
3417     // FIXME:
3418     // some functions check m_quickRedirectComing, and others check for
3419     // FrameLoadTypeRedirectWithLockedHistory.  
3420     bool isRedirect = m_quickRedirectComing || m_policyLoadType == FrameLoadTypeRedirectWithLockedHistory;
3421     m_quickRedirectComing = false;
3422
3423     if (!shouldContinue)
3424         return;
3425
3426     KURL URL = request.url();
3427     
3428     m_documentLoader->replaceRequestURLForAnchorScroll(URL);
3429     if (!isRedirect && !shouldTreatURLAsSameAsCurrent(URL)) {
3430         // NB: must happen after _setURL, since we add based on the current request.
3431         // Must also happen before we openURL and displace the scroll position, since
3432         // adding the BF item will save away scroll state.
3433         
3434         // NB2:  If we were loading a long, slow doc, and the user anchor nav'ed before
3435         // it was done, currItem is now set the that slow doc, and prevItem is whatever was
3436         // before it.  Adding the b/f item will bump the slow doc down to prevItem, even
3437         // though its load is not yet done.  I think this all works out OK, for one because
3438         // we have already saved away the scroll and doc state for the long slow load,
3439         // but it's not an obvious case.
3440
3441         addHistoryItemForFragmentScroll();
3442     }
3443     
3444     scrollToAnchor(URL);
3445     
3446     if (!isRedirect)
3447         // This will clear previousItem from the rest of the frame tree that didn't
3448         // doing any loading. We need to make a pass on this now, since for anchor nav
3449         // we'll not go through a real load and reach Completed state.
3450         checkLoadComplete();
3451  
3452     dispatchDidChangeLocationWithinPage();
3453     m_client->didFinishLoad();
3454 }
3455
3456 void FrameLoader::opened()
3457 {
3458     if (m_loadType == FrameLoadTypeStandard && m_documentLoader->isClientRedirect())
3459         updateHistoryForClientRedirect();
3460
3461     if (m_documentLoader->isLoadingFromCachedPage()) {
3462         m_frame->document()->didRestoreFromCache();
3463         
3464         // Force a layout to update view size and thereby update scrollbars.
3465         m_client->forceLayout();
3466
3467         const ResponseVector& responses = m_documentLoader->responses();
3468         size_t count = responses.size();
3469         for (size_t i = 0; i < count; i++) {
3470             const ResourceResponse& response = responses[i];
3471             // FIXME: If the WebKit client changes or cancels the request, this is not respected.
3472             ResourceError error;
3473             unsigned long identifier;
3474             ResourceRequest request(response.url());
3475             requestFromDelegate(request, identifier, error);
3476             // FIXME: If we get a resource with more than 2B bytes, this code won't do the right thing.
3477             // However, with today's computers and networking speeds, this won't happen in practice.
3478             // Could be an issue with a giant local file.
3479             sendRemainingDelegateMessages(identifier, response, static_cast<int>(response.expectedContentLength()), error);
3480         }
3481         
3482         pageCache()->remove(m_currentHistoryItem.get());
3483
3484         m_documentLoader->setPrimaryLoadComplete(true);
3485
3486         // FIXME: Why only this frame and not parent frames?
3487         checkLoadCompleteForThisFrame();
3488     }
3489 }
3490
3491 void FrameLoader::checkNewWindowPolicy(const NavigationAction& action, const ResourceRequest& request,
3492     PassRefPtr<FormState> formState, const String& frameName)
3493 {
3494     m_policyCheck.set(request, formState, frameName,
3495         callContinueLoadAfterNewWindowPolicy, this);
3496     m_client->dispatchDecidePolicyForNewWindowAction(&FrameLoader::continueAfterNewWindowPolicy,
3497         action, request, frameName);
3498 }
3499
3500 void FrameLoader::continueAfterNewWindowPolicy(PolicyAction policy)
3501 {
3502     PolicyCheck check = m_policyCheck;
3503     m_policyCheck.clear();
3504
3505     switch (policy) {
3506         case PolicyIgnore:
3507             check.clearRequest();
3508             break;
3509         case PolicyDownload:
3510             m_client->startDownload(check.request());
3511             check.clearRequest();
3512             break;
3513         case PolicyUse:
3514             break;
3515     }
3516
3517     check.call(policy == PolicyUse);
3518 }
3519
3520 void FrameLoader::checkNavigationPolicy(const ResourceRequest& request, DocumentLoader* loader,
3521     PassRefPtr<FormState> formState, NavigationPolicyDecisionFunction function, void* argument)
3522 {
3523     NavigationAction action = loader->triggeringAction();
3524     if (action.isEmpty()) {
3525         action = NavigationAction(request.url(), NavigationTypeOther);
3526         loader->setTriggeringAction(action);
3527     }
3528         
3529     // Don't ask more than once for the same request or if we are loading an empty URL.
3530     // This avoids confusion on the part of the client.
3531     if (equalIgnoringHeaderFields(request, loader->lastCheckedRequest()) || (!request.isNull() && request.url().isEmpty())) {
3532         function(argument, request, 0, true);
3533         loader->setLastCheckedRequest(request);
3534         return;
3535     }
3536     
3537     // We are always willing to show alternate content for unreachable URLs;
3538     // treat it like a reload so it maintains the right state for b/f list.
3539     if (loader->substituteData().isValid() && !loader->substituteData().failingURL().isEmpty()) {
3540         if (isBackForwardLoadType(m_policyLoadType))
3541             m_policyLoadType = FrameLoadTypeReload;
3542         function(argument, request, 0, true);
3543         return;
3544     }
3545     
3546     loader->setLastCheckedRequest(request);
3547
3548     m_policyCheck.set(request, formState, function, argument);
3549
3550     m_delegateIsDecidingNavigationPolicy = true;
3551     m_client->dispatchDecidePolicyForNavigationAction(&FrameLoader::continueAfterNavigationPolicy,
3552         action, request);
3553     m_delegateIsDecidingNavigationPolicy = false;
3554 }
3555
3556 void FrameLoader::continueAfterNavigationPolicy(PolicyAction policy)
3557 {
3558     PolicyCheck check = m_policyCheck;
3559     m_policyCheck.clear();
3560
3561     bool shouldContinue = policy == PolicyUse;
3562     
3563     switch (policy) {
3564         case PolicyIgnore:
3565             check.clearRequest();
3566             break;
3567         case PolicyDownload:
3568             m_client->startDownload(check.request());
3569             check.clearRequest();
3570             break;
3571         case PolicyUse: {
3572             ResourceRequest request(check.request());
3573             
3574             if (!m_client->canHandleRequest(request)) {
3575                 handleUnimplementablePolicy(m_client->cannotShowURLError(check.request()));
3576                 check.clearRequest();
3577                 shouldContinue = false;
3578             }
3579             break;
3580         }
3581     }
3582
3583     check.call(shouldContinue);
3584 }
3585
3586 void FrameLoader::callContinueLoadAfterNavigationPolicy(void* argument,
3587     const ResourceRequest& request, PassRefPtr<FormState> formState, bool shouldContinue)
3588 {
3589     FrameLoader* loader = static_cast<FrameLoader*>(argument);
3590     loader->continueLoadAfterNavigationPolicy(request, formState, shouldContinue);
3591 }
3592
3593 void FrameLoader::continueLoadAfterNavigationPolicy(const ResourceRequest& request, PassRefPtr<FormState> formState, bool shouldContinue)
3594 {
3595     // If we loaded an alternate page to replace an unreachableURL, we'll get in here with a
3596     // nil policyDataSource because loading the alternate page will have passed
3597     // through this method already, nested; otherwise, policyDataSource should still be set.
3598     ASSERT(m_policyDocumentLoader || !m_provisionalDocumentLoader->unreachableURL().isEmpty());
3599
3600     bool isTargetItem = m_provisionalHistoryItem ? m_provisionalHistoryItem->isTargetItem() : false;
3601
3602     // Two reasons we can't continue:
3603     //    1) Navigation policy delegate said we can't so request is nil. A primary case of this 
3604     //       is the user responding Cancel to the form repost nag sheet.
3605     //    2) User responded Cancel to an alert popped up by the before unload event handler.
3606     // The "before unload" event handler runs only for the main frame.
3607     bool canContinue = shouldContinue && (!isLoadingMainFrame() || m_frame->shouldClose());
3608
3609     if (!canContinue) {
3610         // If we were waiting for a quick redirect, but the policy delegate decided to ignore it, then we 
3611         // need to report that the client redirect was cancelled.
3612         if (m_quickRedirectComing)
3613             clientRedirectCancelledOrFinished(false);
3614
3615         setPolicyDocumentLoader(0);
3616
3617         // If the navigation request came from the back/forward menu, and we punt on it, we have the 
3618         // problem that we have optimistically moved the b/f cursor already, so move it back.  For sanity, 
3619         // we only do this when punting a navigation for the target frame or top-level frame.  
3620         if ((isTargetItem || isLoadingMainFrame()) && isBackForwardLoadType(m_policyLoadType))
3621             if (Page* page = m_frame->page()) {
3622                 Frame* mainFrame = page->mainFrame();
3623                 if (HistoryItem* resetItem = mainFrame->loader()->m_currentHistoryItem.get())
3624                     page->backForwardList()->goToItem(resetItem);
3625             }
3626         return;
3627     }
3628
3629     FrameLoadType type = m_policyLoadType;
3630     stopAllLoaders();
3631     setProvisionalDocumentLoader(m_policyDocumentLoader.get());
3632     m_loadType = type;
3633     setState(FrameStateProvisional);
3634
3635     setPolicyDocumentLoader(0);
3636
3637     if (isBackForwardLoadType(type) && loadProvisionalItemFromCachedPage())
3638         return;
3639
3640     if (formState)
3641         m_client->dispatchWillSubmitForm(&FrameLoader::continueLoadAfterWillSubmitForm, formState);
3642     else
3643         continueLoadAfterWillSubmitForm();
3644 }
3645
3646
3647 void FrameLoader::callContinueLoadAfterNewWindowPolicy(void* argument,
3648     const ResourceRequest& request, PassRefPtr<FormState> formState, const String& frameName, bool shouldContinue)
3649 {
3650     FrameLoader* loader = static_cast<FrameLoader*>(argument);
3651     loader->continueLoadAfterNewWindowPolicy(request, formState, frameName, shouldContinue);
3652 }
3653
3654 void FrameLoader::continueLoadAfterNewWindowPolicy(const ResourceRequest& request,
3655     PassRefPtr<FormState> formState, const String& frameName, bool shouldContinue)
3656 {
3657     if (!shouldContinue)
3658         return;
3659
3660     RefPtr<Frame> frame = m_frame;
3661     RefPtr<Frame> mainFrame = m_client->dispatchCreatePage();
3662     if (!mainFrame)
3663         return;
3664
3665     if (frameName != "_blank")
3666         mainFrame->tree()->setName(frameName);
3667
3668     mainFrame->loader()->setOpenedByDOM();
3669     mainFrame->loader()->m_client->dispatchShow();
3670     mainFrame->loader()->setOpener(frame.get());
3671     mainFrame->loader()->load(request, NavigationAction(), FrameLoadTypeStandard, formState);
3672 }
3673
3674 void FrameLoader::sendRemainingDelegateMessages(unsigned long identifier, const ResourceResponse& response, int length, const ResourceError& error)
3675 {    
3676     if (!response.isNull())
3677         dispatchDidReceiveResponse(m_documentLoader.get(), identifier, response);
3678     
3679     if (length > 0)
3680         dispatchDidReceiveContentLength(m_documentLoader.get(), identifier, length);
3681     
3682     if (error.isNull())
3683         dispatchDidFinishLoading(m_documentLoader.get(), identifier);
3684     else
3685         m_client->dispatchDidFailLoading(m_documentLoader.get(), identifier, error);
3686 }
3687
3688 void FrameLoader::requestFromDelegate(ResourceRequest& request, unsigned long& identifier, ResourceError& error)
3689 {
3690     ASSERT(!request.isNull());
3691
3692     identifier = 0;
3693     if (Page* page = m_frame->page()) {
3694         identifier = page->progress()->createUniqueIdentifier();
3695         dispatchAssignIdentifierToInitialRequest(identifier, m_documentLoader.get(), request);
3696     }
3697
3698     ResourceRequest newRequest(request);
3699     dispatchWillSendRequest(m_documentLoader.get(), identifier, newRequest, ResourceResponse());
3700
3701     if (newRequest.isNull())
3702         error = m_client->cancelledError(request);
3703     else
3704         error = ResourceError();
3705
3706     request = newRequest;
3707 }
3708
3709 void FrameLoader::loadedResourceFromMemoryCache(const ResourceRequest& request, const ResourceResponse& response, int length)
3710 {
3711     if (dispatchDidLoadResourceFromMemoryCache(m_documentLoader.get(), request, response, length))
3712         return;
3713
3714     unsigned long identifier;
3715     ResourceError error;
3716     ResourceRequest r(request);
3717     requestFromDelegate(r, identifier, error);
3718     sendRemainingDelegateMessages(identifier, response, length, error);
3719 }
3720
3721 void FrameLoader::applyUserAgent(ResourceRequest& request)
3722 {
3723     String userAgent = client()->userAgent(request.url());
3724     ASSERT(!userAgent.isNull());
3725     request.setHTTPUserAgent(userAgent);
3726 }
3727
3728 bool FrameLoader::canGoBackOrForward(int distance) const
3729 {
3730     if (Page* page = m_frame->page()) {
3731         if (distance == 0)
3732             return true;
3733         if (distance > 0 && distance <= page->backForwardList()->forwardListCount())
3734             return true;
3735         if (distance < 0 && -distance <= page->backForwardList()->backListCount())
3736             return true;
3737     }
3738     return false;
3739 }
3740
3741 int FrameLoader::getHistoryLength()
3742 {
3743     if (Page* page = m_frame->page())
3744         return page->backForwardList()->backListCount() + 1;
3745     return 0;
3746 }
3747
3748 KURL FrameLoader::historyURL(int distance)
3749 {
3750     if (Page* page = m_frame->page()) {
3751         BackForwardList* list = page->backForwardList();
3752         HistoryItem* item = list->itemAtIndex(distance);
3753         if (!item) {
3754             if (distance > 0) {
3755                 int forwardListCount = list->forwardListCount();
3756                 if (forwardListCount > 0)
3757                     item = list->itemAtIndex(forwardListCount);
3758             } else {
3759                 int backListCount = list->backListCount();
3760                 if (backListCount > 0)
3761                     item = list->itemAtIndex(-backListCount);
3762             }
3763         }
3764         if (item)
3765             return item->url();
3766     }
3767     return KURL();
3768 }
3769
3770 void FrameLoader::addHistoryItemForFragmentScroll()
3771 {
3772     addBackForwardItemClippedAtTarget(false);
3773 }
3774
3775 bool FrameLoader::loadProvisionalItemFromCachedPage()
3776 {
3777     RefPtr<CachedPage> cachedPage = pageCache()->get(m_provisionalHistoryItem.get());
3778     if (!cachedPage || !cachedPage->document())
3779         return false;
3780     provisionalDocumentLoader()->loadFromCachedPage(cachedPage.release());
3781     return true;
3782 }
3783
3784 void FrameLoader::cachePageForHistoryItem(HistoryItem* item)
3785 {
3786     if (Page* page = m_frame->page()) {
3787         RefPtr<CachedPage> cachedPage = CachedPage::create(page);
3788         cachedPage->setTimeStampToNow();
3789         cachedPage->setDocumentLoader(documentLoader());
3790         m_client->saveDocumentViewToCachedPage(cachedPage.get());
3791
3792         pageCache()->add(item, cachedPage.release());
3793     }
3794 }
3795
3796 bool FrameLoader::shouldTreatURLAsSameAsCurrent(const KURL& URL) const
3797 {
3798     if (!m_currentHistoryItem)
3799         return false;
3800     return URL == m_currentHistoryItem->url() || URL == m_currentHistoryItem->originalURL();
3801 }
3802
3803 PassRefPtr<HistoryItem> FrameLoader::createHistoryItem(bool useOriginal)
3804 {
3805     DocumentLoader* docLoader = documentLoader();
3806     
3807     KURL unreachableURL = docLoader ? docLoader->unreachableURL() : KURL();
3808     
3809     KURL url;
3810     KURL originalURL;
3811
3812     if (!unreachableURL.isEmpty()) {
3813         url = unreachableURL;
3814         originalURL = unreachableURL;
3815     } else {
3816         originalURL = docLoader ? docLoader->originalURL() : KURL();
3817         if (useOriginal)
3818             url = originalURL;
3819         else if (docLoader)
3820             url = docLoader->requestURL();                
3821     }
3822
3823     LOG(History, "WebCoreHistory: Creating item for %s", url.url().ascii());
3824     
3825     // Frames that have never successfully loaded any content
3826     // may have no URL at all. Currently our history code can't
3827     // deal with such things, so we nip that in the bud here.
3828     // Later we may want to learn to live with nil for URL.
3829     // See bug 3368236 and related bugs for more information.
3830     if (url.isEmpty()) 
3831         url = KURL("about:blank");
3832     if (originalURL.isEmpty())
3833         originalURL = KURL("about:blank");
3834     
3835     RefPtr<HistoryItem> item = new HistoryItem(url, m_frame->tree()->name(), m_frame->tree()->parent() ? m_frame->tree()->parent()->tree()->name() : "", docLoader ? docLoader->title() : "");
3836     item->setOriginalURLString(originalURL.url());
3837     
3838     // Save form state if this is a POST
3839     if (docLoader) {
3840         if (useOriginal)
3841             item->setFormInfoFromRequest(docLoader->originalRequest());
3842         else
3843             item->setFormInfoFromRequest(docLoader->request());
3844     }
3845     
3846     // Set the item for which we will save document state
3847     m_previousHistoryItem = m_currentHistoryItem;
3848     m_currentHistoryItem = item;
3849     
3850     return item.release();
3851 }
3852
3853 void FrameLoader::addBackForwardItemClippedAtTarget(bool doClip)
3854 {
3855     if (Page* page = m_frame->page())
3856         if (!documentLoader()->urlForHistory().isEmpty()) {
3857             Frame* mainFrame = page->mainFrame();
3858             ASSERT(mainFrame);
3859             FrameLoader* frameLoader = mainFrame->loader();
3860
3861             if (!frameLoader->m_didPerformFirstNavigation && page->backForwardList()->entries().size() == 1) {
3862                 frameLoader->m_didPerformFirstNavigation = true;
3863                 m_client->didPerformFirstNavigation();
3864             }
3865
3866             RefPtr<HistoryItem> item = frameLoader->createHistoryItemTree(m_frame, doClip);
3867             LOG(BackForward, "WebCoreBackForward - Adding backforward item %p for frame %s", item.get(), documentLoader()->URL().url().ascii());
3868             page->backForwardList()->addItem(item);
3869         }
3870 }
3871
3872 PassRefPtr<HistoryItem> FrameLoader::createHistoryItemTree(Frame* targetFrame, bool clipAtTarget)
3873 {
3874     RefPtr<HistoryItem> bfItem = createHistoryItem(m_frame->tree()->parent() ? true : false);
3875     if (m_previousHistoryItem)
3876         saveScrollPositionAndViewStateToItem(m_previousHistoryItem.get());
3877     if (!(clipAtTarget && m_frame == targetFrame)) {
3878         // save frame state for items that aren't loading (khtml doesn't save those)
3879         saveDocumentState();
3880         for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
3881             bfItem->addChildItem(child->loader()->createHistoryItemTree(targetFrame, clipAtTarget));
3882     }
3883     if (m_frame == targetFrame)
3884         bfItem->setIsTargetItem(true);
3885     return bfItem;
3886 }
3887
3888 void FrameLoader::saveScrollPositionAndViewStateToItem(HistoryItem* item)
3889 {
3890     if (!item || !m_frame->view())
3891         return;
3892         
3893     item->setScrollPoint(IntPoint(m_frame->view()->contentsX(), m_frame->view()->contentsY()));
3894     // FIXME: It would be great to work out a way to put this code in WebCore instead of calling through to the client.
3895     m_client->saveViewStateToItem(item);
3896 }
3897
3898 /*
3899  There is a race condition between the layout and load completion that affects restoring the scroll position.
3900  We try to restore the scroll position at both the first layout and upon load completion.
3901  
3902  1) If first layout happens before the load completes, we want to restore the scroll position then so that the
3903  first time we draw the page is already scrolled to the right place, instead of starting at the top and later
3904  jumping down.  It is possible that the old scroll position is past the part of the doc laid out so far, in
3905  which case the restore silent fails and we will fix it in when we try to restore on doc completion.
3906  2) If the layout happens after the load completes, the attempt to restore at load completion time silently
3907  fails.  We then successfully restore it when the layout happens.
3908 */
3909 void FrameLoader::restoreScrollPositionAndViewState()
3910 {
3911     if (!m_committedFirstRealDocumentLoad)
3912         return;
3913
3914     ASSERT(m_currentHistoryItem);
3915     
3916     // FIXME: As the ASSERT attests, it seems we should always have a currentItem here.
3917     // One counterexample is <rdar://problem/4917290>
3918     // For now, to cover this issue in release builds, there is no technical harm to returning
3919     // early and from a user standpoint - as in the above radar - the previous page load failed 
3920     // so there *is* no scroll or view state to restore!
3921     if (!m_currentHistoryItem)
3922         return;
3923     
3924     // FIXME: It would be great to work out a way to put this code in WebCore instead of calling
3925     // through to the client. It's currently used only for the PDF view on Mac.
3926     m_client->restoreViewState();
3927     
3928     if (FrameView* view = m_frame->view())
3929         if (!view->wasScrolledByUser()) {
3930             const IntPoint& scrollPoint = m_currentHistoryItem->scrollPoint();
3931             view->setContentsPos(scrollPoint.x(), scrollPoint.y());
3932         }
3933 }
3934
3935 void FrameLoader::invalidateCurrentItemCachedPage()
3936 {
3937     // When we are pre-commit, the currentItem is where the pageCache data resides    
3938     CachedPage* cachedPage = pageCache()->get(m_currentHistoryItem.get());
3939
3940     // FIXME: This is a grotesque hack to fix <rdar://problem/4059059> Crash in RenderFlow::detach
3941     // Somehow the PageState object is not properly updated, and is holding onto a stale document.
3942     // Both Xcode and FileMaker see this crash, Safari does not.
3943     
3944     ASSERT(!cachedPage || cachedPage->document() == m_frame->document());
3945     if (cachedPage && cachedPage->document() == m_frame->document()) {
3946         cachedPage->document()->setInPageCache(false);
3947         cachedPage->clear();
3948     }
3949     
3950     if (cachedPage)
3951         pageCache()->remove(m_currentHistoryItem.get());
3952 }
3953
3954 void FrameLoader::saveDocumentState()
3955 {
3956     if (m_creatingInitialEmptyDocument)
3957         return;
3958
3959     // For a standard page load, we will have a previous item set, which will be used to
3960     // store the form state.  However, in some cases we will have no previous item, and
3961     // the current item is the right place to save the state.  One example is when we
3962     // detach a bunch of frames because we are navigating from a site with frames to
3963     // another site.  Another is when saving the frame state of a frame that is not the
3964     // target of the current navigation (if we even decide to save with that granularity).
3965
3966     // Because of previousItem's "masking" of currentItem for this purpose, it's important
3967     // that previousItem be cleared at the end of a page transition.  We leverage the
3968     // checkLoadComplete recursion to achieve this goal.
3969
3970     HistoryItem* item = m_previousHistoryItem ? m_previousHistoryItem.get() : m_currentHistoryItem.get();
3971     if (!item)
3972         return;
3973
3974     Document* document = m_frame->document();
3975     ASSERT(document);
3976     
3977     if (document && item->isCurrentDocument(document)) {
3978         LOG(Loading, "WebCoreLoading %s: saving form state to %p", m_frame->tree()->name().domString().utf8().data(), item);
3979         item->setDocumentState(document->formElementsState());
3980     }
3981 }
3982
3983 // Loads content into this frame, as specified by history item
3984 void FrameLoader::loadItem(HistoryItem* item, FrameLoadType loadType)
3985 {
3986     KURL itemURL = item->url();
3987     KURL itemOriginalURL = item->originalURL();
3988     KURL currentURL;
3989     if (documentLoader())
3990         currentURL = documentLoader()->URL();
3991     RefPtr<FormData> formData = item->formData();
3992
3993     // Are we navigating to an anchor within the page?
3994     // Note if we have child frames we do a real reload, since the child frames might not
3995     // match our current frame structure, or they might not have the right content.  We could
3996     // check for all that as an additional optimization.
3997     // We also do not do anchor-style navigation if we're posting a form.
3998     
3999     if (!formData && !shouldReload(itemURL, currentURL) && urlsMatchItem(item)) {
4000         // Must do this maintenance here, since we don't go through a real page reload
4001         saveScrollPositionAndViewStateToItem(m_currentHistoryItem.get());
4002
4003         if (FrameView* view = m_frame->view())
4004             view->setWasScrolledByUser(false);
4005
4006         m_currentHistoryItem = item;
4007
4008         // FIXME: Form state might need to be saved here too.
4009
4010         // We always call scrollToAnchor here, even if the URL doesn't have an
4011         // anchor fragment. This is so we'll keep the WebCore Frame's URL up-to-date.
4012         scrollToAnchor(item->url());
4013     
4014         // must do this maintenance here, since we don't go through a real page reload
4015         restoreScrollPositionAndViewState();
4016         
4017         // Fake the URL change by updating the data source's request.  This will no longer
4018         // be necessary if we do the better fix described above.
4019         documentLoader()->replaceRequestURLForAnchorScroll(itemURL);
4020
4021         dispatchDidChangeLocationWithinPage();
4022         
4023         // FrameLoaderClient::didFinishLoad() tells the internal load delegate the load finished with no error
4024         dispatchDidFinishLoadToClient();
4025     } else {
4026         // Remember this item so we can traverse any child items as child frames load
4027         m_provisionalHistoryItem = item;
4028
4029         bool inPageCache = false;
4030         
4031         // Check if we'll be using the page cache.  We only use the page cache
4032         // if one exists and it is less than _backForwardCacheExpirationInterval
4033         // seconds old.  If the cache is expired it gets flushed here.
4034         if (RefPtr<CachedPage> cachedPage = pageCache()->get(item)) {
4035             double interval = currentTime() - cachedPage->timeStamp();
4036             
4037             // FIXME: 1800 should not be hardcoded, it should come from
4038             // WebKitBackForwardCacheExpirationIntervalKey in WebKit.
4039             // Or we should remove WebKitBackForwardCacheExpirationIntervalKey.
4040             if (interval <= 1800) {
4041                 load(cachedPage->documentLoader(), loadType, 0);   
4042                 inPageCache = true;
4043             } else {
4044                 LOG(PageCache, "Not restoring page for %s from back/forward cache because cache entry has expired", m_provisionalHistoryItem->url().url().ascii());
4045                 pageCache()->remove(item);
4046             }
4047         }
4048         
4049         if (!inPageCache) {
4050             ResourceRequest request(itemURL);
4051
4052             addExtraFieldsToRequest(request, true, formData);
4053
4054             // If this was a repost that failed the page cache, we might try to repost the form.
4055             NavigationAction action;
4056             if (formData) {
4057                 request.setHTTPMethod("POST");
4058                 request.setHTTPReferrer(item->formReferrer());
4059                 request.setHTTPBody(formData);
4060                 request.setHTTPContentType(item->formContentType());
4061         
4062                 // FIXME: Slight hack to test if the NSURL cache contains the page we're going to.
4063                 // We want to know this before talking to the policy delegate, since it affects whether 
4064                 // we show the DoYouReallyWantToRepost nag.
4065                 //
4066                 // This trick has a small bug (3123893) where we might find a cache hit, but then
4067                 // have the item vanish when we try to use it in the ensuing nav.  This should be
4068                 // extremely rare, but in that case the user will get an error on the navigation.
4069                 
4070                 if (ResourceHandle::willLoadFromCache(request))
4071                     action = NavigationAction(itemURL, loadType, false);
4072                 else {
4073                     request.setCachePolicy(ReloadIgnoringCacheData);
4074                     action = NavigationAction(itemURL, NavigationTypeFormResubmitted);
4075                 }
4076             } else {
4077                 switch (loadType) {
4078                     case FrameLoadTypeReload:
4079                         request.setCachePolicy(ReloadIgnoringCacheData);
4080                         break;
4081                     case FrameLoadTypeBack:
4082                     case FrameLoadTypeForward:
4083                     case FrameLoadTypeIndexedBackForward:
4084                         if (itemURL.protocol() == "https")
4085                             request.setCachePolicy(ReturnCacheDataElseLoad);
4086                         break;
4087                     case FrameLoadTypeStandard:
4088                     case FrameLoadTypeRedirectWithLockedHistory:
4089                         // no-op: leave as protocol default
4090                         // FIXME:  I wonder if we ever hit this case
4091                         break;
4092                     case FrameLoadTypeSame:
4093                     case FrameLoadTypeReloadAllowingStaleData:
4094                     default:
4095                         ASSERT_NOT_REACHED();
4096                 }
4097
4098                 action = NavigationAction(itemOriginalURL, loadType, false);
4099             }
4100
4101             load(request, action, loadType, 0);
4102         }
4103     }
4104 }
4105
4106 // Walk the frame tree and ensure that the URLs match the URLs in the item.
4107 bool FrameLoader::urlsMatchItem(HistoryItem* item) const
4108 {
4109     KURL currentURL = documentLoader()->URL();
4110     
4111     if (!equalIgnoringRef(currentURL, item->url()))
4112         return false;
4113     
4114     const HistoryItemVector& childItems = item->children();
4115     
4116     unsigned size = childItems.size();
4117     for (unsigned i = 0; i < size; ++i) {
4118         Frame* childFrame = m_frame->tree()->child(childItems[i]->target());
4119         if (childFrame && !childFrame->loader()->urlsMatchItem(childItems[i].get()))
4120             return false;
4121     }
4122
4123     return true;
4124 }
4125
4126 // Main funnel for navigating to a previous location (back/forward, non-search snap-back)
4127 // This includes recursion to handle loading into framesets properly
4128 void FrameLoader::goToItem(HistoryItem* targetItem, FrameLoadType type)
4129 {
4130     ASSERT(!m_frame->tree()->parent());
4131     
4132     // shouldGoToHistoryItem is a private delegate method. This is needed to fix:
4133     // <rdar://problem/3951283> can view pages from the back/forward cache that should be disallowed by Parental Controls
4134     // Ultimately, history item navigations should go through the policy delegate. That's covered in:
4135     // <rdar://problem/3979539> back/forward cache navigations should consult policy delegate
4136     if (Page* page = m_frame->page())
4137         if (shouldGoToHistoryItem(targetItem)) {
4138             BackForwardList* bfList = page->backForwardList();
4139             HistoryItem* currentItem = bfList->currentItem();
4140             
4141             // Set the BF cursor before commit, which lets the user quickly click back/forward again.
4142             // - plus, it only makes sense for the top level of the operation through the frametree,
4143             // as opposed to happening for some/one of the page commits that might happen soon
4144             bfList->goToItem(targetItem);
4145             recursiveGoToItem(targetItem, currentItem, type);
4146         }
4147 }
4148
4149 // The general idea here is to traverse the frame tree and the item tree in parallel,
4150 // tracking whether each frame already has the content the item requests.  If there is
4151 // a match (by URL), we just restore scroll position and recurse.  Otherwise we must
4152 // reload that frame, and all its kids.
4153 void FrameLoader::recursiveGoToItem(HistoryItem* item, HistoryItem* fromItem, FrameLoadType type)
4154 {
4155     ASSERT(item);
4156     ASSERT(fromItem);
4157     
4158     KURL itemURL = item->url();
4159     KURL currentURL;
4160     if (documentLoader())
4161         currentURL = documentLoader()->URL();
4162     
4163     // Always reload the target frame of the item we're going to.  This ensures that we will
4164     // do -some- load for the transition, which means a proper notification will be posted
4165     // to the app.
4166     // The exact URL has to match, including fragment.  We want to go through the _load
4167     // method, even if to do a within-page navigation.
4168     // The current frame tree and the frame tree snapshot in the item have to match.
4169     if (!item->isTargetItem() &&
4170         itemURL == currentURL &&
4171         ((m_frame->tree()->name().isEmpty() && item->target().isEmpty()) || m_frame->tree()->name() == item->target()) &&
4172         childFramesMatchItem(item))
4173     {
4174         // This content is good, so leave it alone and look for children that need reloading
4175         // Save form state (works from currentItem, since prevItem is nil)
4176         ASSERT(!m_previousHistoryItem);
4177         saveDocumentState();
4178         saveScrollPositionAndViewStateToItem(m_currentHistoryItem.get());
4179
4180         if (FrameView* view = m_frame->view())
4181             view->setWasScrolledByUser(false);
4182
4183         m_currentHistoryItem = item;
4184                 
4185         // Restore form state (works from currentItem)
4186         restoreDocumentState();
4187         
4188         // Restore the scroll position (we choose to do this rather than going back to the anchor point)
4189         restoreScrollPositionAndViewState();
4190         
4191         const HistoryItemVector& childItems = item->children();
4192         
4193         int size = childItems.size();
4194         for (int i = 0; i < size; ++i) {
4195             String childName = childItems[i]->target();
4196             HistoryItem* fromChildItem = fromItem->childItemWithName(childName);
4197             ASSERT(fromChildItem || fromItem->isTargetItem());
4198             Frame* childFrame = m_frame->tree()->child(childName);
4199             ASSERT(childFrame);
4200             childFrame->loader()->recursiveGoToItem(childItems[i].get(), fromChildItem, type);
4201         }
4202     } else {
4203         loadItem(item, type);
4204     }
4205 }
4206
4207 // helper method that determines whether the subframes described by the item's subitems
4208 // match our own current frameset
4209 bool FrameLoader::childFramesMatchItem(HistoryItem* item) const
4210 {
4211     const HistoryItemVector& childItems = item->children();
4212     if (childItems.size() != m_frame->tree()->childCount())
4213         return false;
4214     
4215     unsigned size = childItems.size();
4216     for (unsigned i = 0; i < size; ++i)
4217         if (!m_frame->tree()->child(childItems[i]->ta