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