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