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