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