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_openedByDOM(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("<html><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::openedByDOM() const
1528 {
1529     return m_openedByDOM;
1530 }
1531
1532 void FrameLoader::setOpenedByDOM()
1533 {
1534     m_openedByDOM = 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         RefPtr<FormState> formState;
1811         if (submitForm && !formValues.isEmpty())
1812             formState = FormState::create(submitForm, formValues, m_frame);
1813         
1814         load(request.resourceRequest().url(), referrer, loadType, 
1815             request.frameName(), event, formState.release());
1816     } else
1817         post(request.resourceRequest().url(), referrer, request.frameName(), 
1818             request.resourceRequest().httpBody(), request.resourceRequest().httpContentType(), event, submitForm, formValues);
1819
1820     if (targetFrame && targetFrame != m_frame)
1821         targetFrame->page()->chrome()->focus();
1822 }
1823
1824 void FrameLoader::load(const KURL& URL, const String& referrer, FrameLoadType newLoadType,
1825     const String& frameName, Event* event, PassRefPtr<FormState> formState)
1826 {
1827     bool isFormSubmission = formState;
1828     
1829     ResourceRequest request(URL);
1830     if (!referrer.isEmpty())
1831         request.setHTTPReferrer(referrer);
1832     addExtraFieldsToRequest(request, true, event || isFormSubmission);
1833     if (newLoadType == FrameLoadTypeReload)
1834         request.setCachePolicy(ReloadIgnoringCacheData);
1835
1836     ASSERT(newLoadType != FrameLoadTypeSame);
1837
1838     NavigationAction action(URL, newLoadType, isFormSubmission, event);
1839
1840     if (!frameName.isEmpty()) {
1841         if (Frame* targetFrame = m_frame->tree()->find(frameName))
1842             targetFrame->loader()->load(URL, referrer, newLoadType, String(), event, formState);
1843         else
1844             checkNewWindowPolicy(action, request, formState, 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,
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);
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 || (m_provisionalDocumentLoader && !m_creatingInitialEmptyDocument); 
2246 }
2247
2248 void FrameLoader::setDocumentLoader(DocumentLoader* loader)
2249 {
2250     if (!loader && !m_documentLoader)
2251         return;
2252     
2253     ASSERT(loader != m_documentLoader);
2254     ASSERT(!loader || loader->frameLoader() == this);
2255
2256     m_client->prepareForDataSourceReplacement();
2257     detachChildren();
2258     if (m_documentLoader)
2259         m_documentLoader->detachFromFrame();
2260
2261     m_documentLoader = loader;
2262 }
2263
2264 DocumentLoader* FrameLoader::documentLoader() const
2265 {
2266     return m_documentLoader.get();
2267 }
2268
2269 void FrameLoader::setPolicyDocumentLoader(DocumentLoader* loader)
2270 {
2271     if (m_policyDocumentLoader == loader)
2272         return;
2273
2274     ASSERT(m_frame);
2275     if (loader)
2276         loader->setFrame(m_frame);
2277     if (m_policyDocumentLoader
2278             && m_policyDocumentLoader != m_provisionalDocumentLoader
2279             && m_policyDocumentLoader != m_documentLoader)
2280         m_policyDocumentLoader->detachFromFrame();
2281
2282     m_policyDocumentLoader = loader;
2283 }
2284    
2285 DocumentLoader* FrameLoader::provisionalDocumentLoader()
2286 {
2287     return m_provisionalDocumentLoader.get();
2288 }
2289
2290 void FrameLoader::setProvisionalDocumentLoader(DocumentLoader* loader)
2291 {
2292     ASSERT(!loader || !m_provisionalDocumentLoader);
2293     ASSERT(!loader || loader->frameLoader() == this);
2294
2295     if (m_provisionalDocumentLoader && m_provisionalDocumentLoader != m_documentLoader)
2296         m_provisionalDocumentLoader->detachFromFrame();
2297
2298     m_provisionalDocumentLoader = loader;
2299 }
2300
2301 FrameState FrameLoader::state() const
2302 {
2303     return m_state;
2304 }
2305
2306 double FrameLoader::timeOfLastCompletedLoad()
2307 {
2308     return storedTimeOfLastCompletedLoad;
2309 }
2310
2311 void FrameLoader::setState(FrameState newState)
2312 {    
2313     m_state = newState;
2314     
2315     if (newState == FrameStateProvisional)
2316         provisionalLoadStarted();
2317     else if (newState == FrameStateComplete) {
2318         frameLoadCompleted();
2319         storedTimeOfLastCompletedLoad = currentTime();
2320         if (m_documentLoader)
2321             m_documentLoader->stopRecordingResponses();
2322     }
2323 }
2324
2325 void FrameLoader::clearProvisionalLoad()
2326 {
2327     setProvisionalDocumentLoader(0);
2328     if (m_frame->page())
2329         m_frame->page()->progress()->progressCompleted(m_frame);
2330     setState(FrameStateComplete);
2331 }
2332
2333 void FrameLoader::markLoadComplete()
2334 {
2335     setState(FrameStateComplete);
2336 }
2337
2338 void FrameLoader::commitProvisionalLoad(PassRefPtr<CachedPage> prpCachedPage)
2339 {
2340     RefPtr<CachedPage> cachedPage = prpCachedPage;
2341     RefPtr<DocumentLoader> pdl = m_provisionalDocumentLoader;
2342     
2343     if (m_loadType != FrameLoadTypeReplace)
2344         closeOldDataSources();
2345     
2346     if (!cachedPage)
2347         m_client->makeRepresentation(pdl.get());
2348     
2349     transitionToCommitted(cachedPage);
2350     
2351     // Call clientRedirectCancelledOrFinished() here so that the frame load delegate is notified that the redirect's
2352     // status has changed, if there was a redirect.  The frame load delegate may have saved some state about
2353     // the redirect in its -webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:.  Since we are
2354     // just about to commit a new page, there cannot possibly be a pending redirect at this point.
2355     if (m_sentRedirectNotification)
2356         clientRedirectCancelledOrFinished(false);
2357     
2358     if (cachedPage && cachedPage->document()) {
2359         open(*cachedPage);
2360         cachedPage->clear();
2361     } else {        
2362         KURL url = pdl->substituteData().responseURL();
2363         if (url.isEmpty())
2364             url = pdl->URL();
2365         if (url.isEmpty())
2366             url = pdl->responseURL();
2367         if (url.isEmpty())
2368             url = "about:blank";
2369
2370         didOpenURL(url);
2371     }
2372     opened();
2373 }
2374
2375 void FrameLoader::transitionToCommitted(PassRefPtr<CachedPage> cachedPage)
2376 {
2377     ASSERT(m_client->hasWebView());
2378     ASSERT(m_state == FrameStateProvisional);
2379
2380     if (m_state != FrameStateProvisional)
2381         return;
2382
2383     m_client->setCopiesOnScroll();
2384     updateHistoryForCommit();
2385
2386     // The call to closeURL() invokes the unload event handler, which can execute arbitrary
2387     // JavaScript. If the script initiates a new load, we need to abandon the current load,
2388     // or the two will stomp each other.
2389     DocumentLoader* pdl = m_provisionalDocumentLoader.get();
2390     if (m_documentLoader)
2391         closeURL();
2392     if (pdl != m_provisionalDocumentLoader)
2393         return;
2394
2395     // Nothing else can interupt this commit - set the Provisional->Committed transition in stone
2396     if (m_documentLoader)
2397         m_documentLoader->stopLoadingSubresources();
2398     if (m_documentLoader)
2399         m_documentLoader->stopLoadingPlugIns();
2400
2401     setDocumentLoader(m_provisionalDocumentLoader.get());
2402     setProvisionalDocumentLoader(0);
2403     setState(FrameStateCommittedPage);
2404
2405     // Handle adding the URL to the back/forward list.
2406     DocumentLoader* dl = m_documentLoader.get();
2407     String ptitle = dl->title();
2408
2409     switch (m_loadType) {
2410         case FrameLoadTypeForward:
2411         case FrameLoadTypeBack:
2412         case FrameLoadTypeIndexedBackForward:
2413             if (m_frame->page()->backForwardList()) {
2414                 updateHistoryForBackForwardNavigation();
2415
2416                 // Create a document view for this document, or used the cached view.
2417                 if (cachedPage)
2418                     m_client->setDocumentViewFromCachedPage(cachedPage.get());
2419                 else
2420                     m_client->makeDocumentView();
2421             }
2422             break;
2423
2424         case FrameLoadTypeReload:
2425         case FrameLoadTypeSame:
2426         case FrameLoadTypeReplace:
2427             updateHistoryForReload();
2428             m_client->makeDocumentView();
2429             break;
2430
2431         // FIXME - just get rid of this case, and merge FrameLoadTypeReloadAllowingStaleData with the above case
2432         case FrameLoadTypeReloadAllowingStaleData:
2433             m_client->makeDocumentView();
2434             break;
2435
2436         case FrameLoadTypeStandard:
2437             updateHistoryForStandardLoad();
2438             m_client->makeDocumentView();
2439             break;
2440
2441         case FrameLoadTypeInternal:
2442             updateHistoryForInternalLoad();
2443             m_client->makeDocumentView();
2444             break;
2445
2446         // FIXME Remove this check when dummy ds is removed (whatever "dummy ds" is).
2447         // An exception should be thrown if we're in the FrameLoadTypeUninitialized state.
2448         default:
2449             ASSERT_NOT_REACHED();
2450     }
2451
2452     m_responseMIMEType = dl->responseMIMEType();
2453
2454     // Tell the client we've committed this URL.
2455     ASSERT(m_client->hasFrameView());
2456
2457     if (m_creatingInitialEmptyDocument)
2458         return;
2459
2460     m_committedFirstRealDocumentLoad = true;
2461
2462     m_client->dispatchDidCommitLoad();
2463     
2464     // If we have a title let the WebView know about it.
2465     if (!ptitle.isNull())
2466         m_client->dispatchDidReceiveTitle(ptitle);
2467 }
2468
2469 bool FrameLoader::privateBrowsingEnabled() const
2470 {
2471     return m_client->privateBrowsingEnabled();
2472 }
2473
2474 void FrameLoader::clientRedirectCancelledOrFinished(bool cancelWithLoadInProgress)
2475 {
2476     // Note that -webView:didCancelClientRedirectForFrame: is called on the frame load delegate even if
2477     // the redirect succeeded.  We should either rename this API, or add a new method, like
2478     // -webView:didFinishClientRedirectForFrame:
2479     m_client->dispatchDidCancelClientRedirect();
2480
2481     if (!cancelWithLoadInProgress)
2482         m_quickRedirectComing = false;
2483
2484     m_sentRedirectNotification = false;
2485 }
2486
2487 void FrameLoader::clientRedirected(const KURL& URL, double seconds, double fireDate, bool lockHistory, bool isJavaScriptFormAction)
2488 {
2489     m_client->dispatchWillPerformClientRedirect(URL, seconds, fireDate);
2490     
2491     // Remember that we sent a redirect notification to the frame load delegate so that when we commit
2492     // the next provisional load, we can send a corresponding -webView:didCancelClientRedirectForFrame:
2493     m_sentRedirectNotification = true;
2494     
2495     // If a "quick" redirect comes in an, we set a special mode so we treat the next
2496     // load as part of the same navigation. If we don't have a document loader, we have
2497     // no "original" load on which to base a redirect, so we treat the redirect as a normal load.
2498     m_quickRedirectComing = lockHistory && m_documentLoader && !isJavaScriptFormAction;
2499 }
2500
2501 bool FrameLoader::shouldReload(const KURL& currentURL, const KURL& destinationURL)
2502 {
2503     // This function implements the rule: "Don't reload if navigating by fragment within
2504     // the same URL, but do reload if going to a new URL or to the same URL with no
2505     // fragment identifier at all."
2506     if (!currentURL.hasRef() && !destinationURL.hasRef())
2507         return true;
2508     return !equalIgnoringRef(currentURL, destinationURL);
2509 }
2510
2511 void FrameLoader::closeOldDataSources()
2512 {
2513     // FIXME: Is it important for this traversal to be postorder instead of preorder?
2514     // If so, add helpers for postorder traversal, and use them. If not, then lets not
2515     // use a recursive algorithm here.
2516     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
2517         child->loader()->closeOldDataSources();
2518     
2519     if (m_documentLoader)
2520         m_client->dispatchWillClose();
2521
2522     m_client->setMainFrameDocumentReady(false); // stop giving out the actual DOMDocument to observers
2523 }
2524
2525 void FrameLoader::open(CachedPage& cachedPage)
2526 {
2527     ASSERT(m_frame->page()->mainFrame() == m_frame);
2528
2529     cancelRedirection();
2530
2531     // We still have to close the previous part page.
2532     closeURL();
2533
2534     m_isComplete = false;
2535     
2536     // Don't re-emit the load event.
2537     m_wasLoadEventEmitted = true;
2538     
2539     // Delete old status bar messages (if it _was_ activated on last URL).
2540     if (m_frame->settings()->isJavaScriptEnabled()) {
2541         m_frame->setJSStatusBarText(String());
2542         m_frame->setJSDefaultStatusBarText(String());
2543     }
2544
2545     KURL URL = cachedPage.URL();
2546
2547     if (URL.protocol().startsWith("http") && !URL.host().isEmpty() && URL.path().isEmpty())
2548         URL.setPath("/");
2549     
2550     m_URL = URL;
2551     m_workingURL = URL;
2552
2553     started();
2554
2555     clear();
2556
2557     Document* document = cachedPage.document();
2558     ASSERT(document);
2559     document->setInPageCache(false);
2560
2561     m_needsClear = true;
2562     m_isComplete = false;
2563     m_wasLoadEventEmitted = false;
2564     m_outgoingReferrer = URL.url();
2565
2566     FrameView* view = cachedPage.view();
2567     if (view)
2568         view->setWasScrolledByUser(false);
2569     m_frame->setView(view);
2570     
2571     m_frame->setDocument(document);
2572     m_decoder = document->decoder();
2573
2574     updatePolicyBaseURL();
2575
2576     cachedPage.restore(m_frame->page());
2577
2578     checkCompleted();
2579 }
2580
2581 bool FrameLoader::isStopping() const
2582 {
2583     return activeDocumentLoader()->isStopping();
2584 }
2585
2586 void FrameLoader::finishedLoading()
2587 {
2588     // Retain because the stop may release the last reference to it.
2589     RefPtr<Frame> protect(m_frame);
2590
2591     RefPtr<DocumentLoader> dl = activeDocumentLoader();
2592     dl->finishedLoading();
2593     if (!dl->mainDocumentError().isNull() || !dl->frameLoader())
2594         return;
2595     dl->setPrimaryLoadComplete(true);
2596     m_client->dispatchDidLoadMainResource(dl.get());
2597     checkLoadComplete();
2598 }
2599
2600 KURL FrameLoader::URL() const
2601 {
2602     return activeDocumentLoader()->URL();
2603 }
2604
2605 bool FrameLoader::isArchiveLoadPending(ResourceLoader* loader) const
2606 {
2607     return m_client->isArchiveLoadPending(loader);
2608 }
2609
2610 bool FrameLoader::isHostedByObjectElement() const
2611 {
2612     HTMLFrameOwnerElement* owner = m_frame->ownerElement();
2613     return owner && owner->hasTagName(objectTag);
2614 }
2615
2616 bool FrameLoader::isLoadingMainFrame() const
2617 {
2618     Page* page = m_frame->page();
2619     return page && m_frame == page->mainFrame();
2620 }
2621
2622 bool FrameLoader::canShowMIMEType(const String& MIMEType) const
2623 {
2624     return m_client->canShowMIMEType(MIMEType);
2625 }
2626
2627 bool FrameLoader::representationExistsForURLScheme(const String& URLScheme)
2628 {
2629     return m_client->representationExistsForURLScheme(URLScheme);
2630 }
2631
2632 String FrameLoader::generatedMIMETypeForURLScheme(const String& URLScheme)
2633 {
2634     return m_client->generatedMIMETypeForURLScheme(URLScheme);
2635 }
2636
2637 void FrameLoader::cancelContentPolicyCheck()
2638 {
2639     m_client->cancelPolicyCheck();
2640     m_policyCheck.clear();
2641 }
2642
2643 void FrameLoader::didReceiveServerRedirectForProvisionalLoadForFrame()
2644 {
2645     m_client->dispatchDidReceiveServerRedirectForProvisionalLoad();
2646 }
2647
2648 void FrameLoader::finishedLoadingDocument(DocumentLoader* loader)
2649 {
2650     m_client->finishedLoading(loader);
2651 }
2652
2653 bool FrameLoader::isReplacing() const
2654 {
2655     return m_loadType == FrameLoadTypeReplace;
2656 }
2657
2658 void FrameLoader::setReplacing()
2659 {
2660     m_loadType = FrameLoadTypeReplace;
2661 }
2662
2663 void FrameLoader::revertToProvisional(DocumentLoader* loader)
2664 {
2665     m_client->revertToProvisionalState(loader);
2666 }
2667
2668 bool FrameLoader::subframeIsLoading() const
2669 {
2670     // It's most likely that the last added frame is the last to load so we walk backwards.
2671     for (Frame* child = m_frame->tree()->lastChild(); child; child = child->tree()->previousSibling()) {
2672         FrameLoader* childLoader = child->loader();
2673         DocumentLoader* documentLoader = childLoader->documentLoader();
2674         if (documentLoader && documentLoader->isLoadingInAPISense())
2675             return true;
2676         documentLoader = childLoader->provisionalDocumentLoader();
2677         if (documentLoader && documentLoader->isLoadingInAPISense())
2678             return true;
2679     }
2680     return false;
2681 }
2682
2683 void FrameLoader::willChangeTitle(DocumentLoader* loader)
2684 {
2685     m_client->willChangeTitle(loader);
2686 }
2687
2688 FrameLoadType FrameLoader::loadType() const
2689 {
2690     return m_loadType;
2691 }
2692
2693 void FrameLoader::stopPolicyCheck()
2694 {
2695     m_client->cancelPolicyCheck();
2696     PolicyCheck check = m_policyCheck;
2697     m_policyCheck.clear();
2698     check.cancel();
2699 }
2700
2701 void FrameLoader::checkLoadCompleteForThisFrame()
2702 {
2703     ASSERT(m_client->hasWebView());
2704
2705     switch (m_state) {
2706         case FrameStateProvisional: {
2707             if (m_delegateIsHandlingProvisionalLoadError)
2708                 return;
2709
2710             RefPtr<DocumentLoader> pdl = m_provisionalDocumentLoader;
2711             if (!pdl)
2712                 return;
2713                 
2714             // If we've received any errors we may be stuck in the provisional state and actually complete.
2715             const ResourceError& error = pdl->mainDocumentError();
2716             if (error.isNull())
2717                 return;
2718
2719             // Check all children first.
2720             RefPtr<HistoryItem> item;
2721             if (isBackForwardLoadType(loadType()) && m_frame == m_frame->page()->mainFrame())
2722                 item = m_currentHistoryItem;
2723                 
2724             bool shouldReset = true;
2725             if (!pdl->isLoadingInAPISense()) {
2726                 m_delegateIsHandlingProvisionalLoadError = true;
2727                 m_client->dispatchDidFailProvisionalLoad(error);
2728                 m_delegateIsHandlingProvisionalLoadError = false;
2729
2730                 // FIXME: can stopping loading here possibly have any effect, if isLoading is false,
2731                 // which it must be to be in this branch of the if? And is it OK to just do a full-on
2732                 // stopAllLoaders instead of stopLoadingSubframes?
2733                 stopLoadingSubframes();
2734                 pdl->stopLoading();
2735
2736                 // Finish resetting the load state, but only if another load hasn't been started by the
2737                 // delegate callback.
2738                 if (pdl == m_provisionalDocumentLoader)
2739                     clearProvisionalLoad();
2740                 else {
2741                     KURL unreachableURL = m_provisionalDocumentLoader->unreachableURL();
2742                     if (!unreachableURL.isEmpty() && unreachableURL == pdl->request().url())
2743                         shouldReset = false;
2744                 }
2745             }
2746             if (shouldReset && item && m_frame->page())
2747                  m_frame->page()->backForwardList()->goToItem(item.get());
2748
2749             return;
2750         }
2751         
2752         case FrameStateCommittedPage: {
2753             DocumentLoader* dl = m_documentLoader.get();            
2754             if (!dl || dl->isLoadingInAPISense())
2755                 return;
2756
2757             markLoadComplete();
2758
2759             // FIXME: Is this subsequent work important if we already navigated away?
2760             // Maybe there are bugs because of that, or extra work we can skip because
2761             // the new page is ready.
2762
2763             m_client->forceLayoutForNonHTML();
2764              
2765             // If the user had a scroll point, scroll to it, overriding the anchor point if any.
2766             if ((isBackForwardLoadType(m_loadType) || m_loadType == FrameLoadTypeReload)
2767                     && m_frame->page() && m_frame->page()->backForwardList())
2768                 restoreScrollPositionAndViewState();
2769
2770             if (m_creatingInitialEmptyDocument)
2771                 return;
2772
2773             const ResourceError& error = dl->mainDocumentError();
2774             if (!error.isNull())
2775                 m_client->dispatchDidFailLoad(error);
2776             else
2777                 m_client->dispatchDidFinishLoad();
2778
2779             if (m_frame->page())
2780                 m_frame->page()->progress()->progressCompleted(m_frame);
2781             return;
2782         }
2783         
2784         case FrameStateComplete:
2785             // Even if already complete, we might have set a previous item on a frame that
2786             // didn't do any data loading on the past transaction. Make sure to clear these out.
2787             m_client->frameLoadCompleted();
2788             return;
2789     }
2790
2791     ASSERT_NOT_REACHED();
2792 }
2793
2794 void FrameLoader::continueAfterContentPolicy(PolicyAction policy)
2795 {
2796     PolicyCheck check = m_policyCheck;
2797     m_policyCheck.clear();
2798     check.call(policy);
2799 }
2800
2801 void FrameLoader::continueLoadAfterWillSubmitForm(PolicyAction)
2802 {
2803     if (!m_provisionalDocumentLoader)
2804         return;
2805
2806     m_provisionalDocumentLoader->prepareForLoadStart();
2807
2808     DocumentLoader* activeDocLoader = activeDocumentLoader();
2809     if (activeDocLoader && activeDocLoader->isLoadingMainResource())
2810         return;
2811
2812     m_provisionalDocumentLoader->setLoadingFromCachedPage(false);
2813
2814     unsigned long identifier = m_frame->page()->progress()->createUniqueIdentifier();
2815     m_client->assignIdentifierToInitialRequest(identifier, m_provisionalDocumentLoader.get(), m_provisionalDocumentLoader->originalRequest());
2816
2817     if (!m_provisionalDocumentLoader->startLoadingMainResource(identifier))
2818         m_provisionalDocumentLoader->updateLoading();
2819 }
2820
2821 void FrameLoader::didFirstLayout()
2822 {
2823     if (isBackForwardLoadType(m_loadType) && m_frame->page() && m_frame->page()->backForwardList())
2824         restoreScrollPositionAndViewState();
2825
2826     m_firstLayoutDone = true;
2827     m_client->dispatchDidFirstLayout();
2828 }
2829
2830 void FrameLoader::frameLoadCompleted()
2831 {
2832     m_client->frameLoadCompleted();
2833
2834     // After a canceled provisional load, firstLayoutDone is false.
2835     // Reset it to true if we're displaying a page.
2836     if (m_documentLoader)
2837         m_firstLayoutDone = true;
2838 }
2839
2840 bool FrameLoader::firstLayoutDone() const
2841 {
2842     return m_firstLayoutDone;
2843 }
2844
2845 bool FrameLoader::isQuickRedirectComing() const
2846 {
2847     return m_quickRedirectComing;
2848 }
2849
2850 void FrameLoader::detachChildren()
2851 {
2852     // FIXME: Is it really necessary to do this in reverse order?
2853     Frame* previous;
2854     for (Frame* child = m_frame->tree()->lastChild(); child; child = previous) {
2855         previous = child->tree()->previousSibling();
2856         child->loader()->detachFromParent();
2857     }
2858 }
2859
2860 void FrameLoader::recursiveCheckLoadComplete()
2861 {
2862     Vector<RefPtr<Frame>, 10> frames;
2863     
2864     for (RefPtr<Frame> frame = m_frame->tree()->firstChild(); frame; frame = frame->tree()->nextSibling())
2865         frames.append(frame);
2866     
2867     unsigned size = frames.size();
2868     for (unsigned i = 0; i < size; i++)
2869         frames[i]->loader()->recursiveCheckLoadComplete();
2870     
2871     checkLoadCompleteForThisFrame();
2872 }
2873
2874 // Called every time a resource is completely loaded, or an error is received.
2875 void FrameLoader::checkLoadComplete()
2876 {
2877     ASSERT(m_client->hasWebView());
2878     
2879     // FIXME: Always traversing the entire frame tree is a bit inefficient, but 
2880     // is currently needed in order to null out the previous history item for all frames.
2881     if (Page* page = m_frame->page())
2882         page->mainFrame()->loader()->recursiveCheckLoadComplete();
2883 }
2884
2885 int FrameLoader::numPendingOrLoadingRequests(bool recurse) const
2886 {
2887     if (!recurse)
2888         return numRequests(m_frame->document());
2889
2890     int count = 0;
2891     for (Frame* frame = m_frame; frame; frame = frame->tree()->traverseNext(m_frame))
2892         count += numRequests(frame->document());
2893     return count;
2894 }
2895
2896 FrameLoaderClient* FrameLoader::client() const
2897 {
2898     return m_client;
2899 }
2900
2901 void FrameLoader::submitForm(const FrameLoadRequest& request, Event* event)
2902 {
2903     // FIXME: We'd like to remove this altogether and fix the multiple form submission issue another way.
2904     // We do not want to submit more than one form from the same page,
2905     // nor do we want to submit a single form more than once.
2906     // This flag prevents these from happening; not sure how other browsers prevent this.
2907     // The flag is reset in each time we start handle a new mouse or key down event, and
2908     // also in setView since this part may get reused for a page from the back/forward cache.
2909     // The form multi-submit logic here is only needed when we are submitting a form that affects this frame.
2910     // FIXME: Frame targeting is only one of the ways the submission could end up doing something other
2911     // than replacing this frame's content, so this check is flawed. On the other hand, the check is hardly
2912     // needed any more now that we reset m_submittedFormURL on each mouse or key down event.
2913     Frame* target = m_frame->tree()->find(request.frameName());
2914     if (m_frame->tree()->isDescendantOf(target)) {
2915         if (m_submittedFormURL == request.resourceRequest().url())
2916             return;
2917         m_submittedFormURL = request.resourceRequest().url();
2918     }
2919
2920     // FIXME: Why do we always pass true for userGesture?
2921     load(request, true, event, m_formAboutToBeSubmitted.get(), m_formValuesAboutToBeSubmitted);
2922
2923     clearRecordedFormValues();
2924 }
2925
2926 void FrameLoader::urlSelected(const FrameLoadRequest& request, Event* event, bool userGesture)
2927 {
2928     FrameLoadRequest copy = request;
2929     if (copy.resourceRequest().httpReferrer().isEmpty())
2930         copy.resourceRequest().setHTTPReferrer(m_outgoingReferrer);
2931
2932     load(copy, userGesture, event, 0, HashMap<String, String>());
2933 }
2934     
2935 String FrameLoader::userAgent(const KURL& url) const
2936 {
2937     return m_client->userAgent(url);
2938 }
2939
2940 void FrameLoader::tokenizerProcessedData()
2941 {
2942     ASSERT(m_frame->page());
2943     ASSERT(m_frame->document());
2944
2945     checkCompleted();
2946 }
2947
2948 void FrameLoader::didTellBridgeAboutLoad(const String& URL)
2949 {
2950     m_urlsBridgeKnowsAbout.add(URL);
2951 }
2952
2953 bool FrameLoader::haveToldBridgeAboutLoad(const String& URL)
2954 {
2955     return m_urlsBridgeKnowsAbout.contains(URL);
2956 }
2957
2958 void FrameLoader::handledOnloadEvents()
2959 {
2960     m_client->dispatchDidHandleOnloadEvents();
2961 }
2962
2963 void FrameLoader::frameDetached()
2964 {
2965     stopAllLoaders();
2966     detachFromParent();
2967 }
2968
2969 void FrameLoader::detachFromParent()
2970 {
2971     RefPtr<Frame> protect(m_frame);
2972
2973     closeURL();
2974     stopAllLoaders();
2975     saveScrollPositionAndViewStateToItem(currentHistoryItem());
2976     detachChildren();
2977     m_client->detachedFromParent2();
2978     setDocumentLoader(0);
2979     m_client->detachedFromParent3();
2980     if (Frame* parent = m_frame->tree()->parent()) {
2981         parent->tree()->removeChild(m_frame);
2982         parent->loader()->scheduleCheckCompleted();
2983     } else {
2984         m_frame->setView(0);
2985         m_frame->pageDestroyed();
2986     }
2987 #if PLATFORM(MAC)
2988     [m_frame->bridge() close];
2989 #endif
2990     m_client->detachedFromParent4();
2991 }
2992
2993 void FrameLoader::dispatchDidChangeLocationWithinPage()
2994 {
2995     m_client->dispatchDidChangeLocationWithinPage();
2996 }
2997
2998 void FrameLoader::dispatchDidFinishLoadToClient()
2999 {
3000     m_client->didFinishLoad();
3001 }
3002
3003 void FrameLoader::updateGlobalHistoryForStandardLoad(const KURL& url)
3004 {
3005     m_client->updateGlobalHistoryForStandardLoad(url);
3006 }
3007
3008 void FrameLoader::updateGlobalHistoryForReload(const KURL& url)
3009 {
3010     m_client->updateGlobalHistoryForReload(url);
3011 }
3012
3013 bool FrameLoader::shouldGoToHistoryItem(HistoryItem* item) const
3014 {
3015     return m_client->shouldGoToHistoryItem(item);
3016 }
3017
3018 void FrameLoader::addExtraFieldsToRequest(ResourceRequest& request, bool mainResource, bool alwaysFromRequest)
3019 {
3020     applyUserAgent(request);
3021     
3022     if (m_loadType == FrameLoadTypeReload)
3023         request.setHTTPHeaderField("Cache-Control", "max-age=0");
3024     
3025     // Don't set the cookie policy URL if it's already been set.
3026     if (request.mainDocumentURL().isEmpty()) {
3027         if (mainResource && (isLoadingMainFrame() || alwaysFromRequest))
3028             request.setMainDocumentURL(request.url());
3029         else
3030             request.setMainDocumentURL(m_frame->page()->mainFrame()->loader()->url());
3031     }
3032     
3033     if (mainResource)
3034         request.setHTTPAccept("text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5");
3035 }
3036
3037 void FrameLoader::committedLoad(DocumentLoader* loader, const char* data, int length)
3038 {
3039     m_client->committedLoad(loader, data, length);
3040 }
3041
3042 void FrameLoader::post(const KURL& URL, const String& referrer, const String& frameName, PassRefPtr<FormData> formData, 
3043     const String& contentType, Event* event, HTMLFormElement* form, const HashMap<String, String>& formValues)
3044 {
3045     // When posting, use the NSURLRequestReloadIgnoringCacheData load flag.
3046     // This prevents a potential bug which may cause a page with a form that uses itself
3047     // as an action to be returned from the cache without submitting.
3048
3049     // FIXME: Where's the code that implements what the comment above says?
3050
3051     ResourceRequest request(URL);
3052     addExtraFieldsToRequest(request, true, true);
3053
3054     if (!referrer.isEmpty())
3055         request.setHTTPReferrer(referrer);
3056     request.setHTTPMethod("POST");
3057     request.setHTTPBody(formData);
3058     request.setHTTPContentType(contentType);
3059
3060     NavigationAction action(URL, FrameLoadTypeStandard, true, event);
3061
3062     RefPtr<FormState> formState;
3063     if (form && !formValues.isEmpty())
3064         formState = FormState::create(form, formValues, m_frame);
3065
3066     if (!frameName.isEmpty()) {
3067         if (Frame* targetFrame = m_frame->tree()->find(frameName))
3068             targetFrame->loader()->load(request, action, FrameLoadTypeStandard, formState.release());
3069         else
3070             checkNewWindowPolicy(action, request, formState.release(), frameName);
3071     } else
3072         load(request, action, FrameLoadTypeStandard, formState.release());
3073 }
3074
3075 bool FrameLoader::isReloading() const
3076 {
3077     return documentLoader()->request().cachePolicy() == ReloadIgnoringCacheData;
3078 }
3079
3080 void FrameLoader::loadEmptyDocumentSynchronously()
3081 {
3082     ResourceRequest request(KURL(""));
3083     load(request);
3084 }
3085
3086 void FrameLoader::loadResourceSynchronously(const ResourceRequest& request, ResourceError& error, ResourceResponse& response, Vector<char>& data)
3087 {
3088     // Since this is a subresource, we can load any URL (we ignore the return value).
3089     // But we still want to know whether we should hide the referrer or not, so we call the canLoad method.
3090     String referrer = m_outgoingReferrer;
3091     if (shouldHideReferrer(request.url(), referrer))
3092         referrer = String();
3093     
3094     ResourceRequest initialRequest = request;
3095     initialRequest.setTimeoutInterval(10);
3096     
3097     if (initialRequest.isConditional())
3098         initialRequest.setCachePolicy(ReloadIgnoringCacheData);
3099     else
3100         initialRequest.setCachePolicy(documentLoader()->request().cachePolicy());
3101     
3102     if (!referrer.isEmpty())
3103         initialRequest.setHTTPReferrer(referrer);
3104     
3105     initialRequest.setMainDocumentURL(m_frame->page()->mainFrame()->loader()->documentLoader()->request().url());
3106     initialRequest.setHTTPUserAgent(client()->userAgent(request.url()));
3107     
3108     unsigned long identifier = 0;    
3109     ResourceRequest newRequest(initialRequest);
3110     requestFromDelegate(newRequest, identifier, error);
3111
3112     if (error.isNull()) {
3113         ASSERT(!newRequest.isNull());
3114         didTellBridgeAboutLoad(newRequest.url().url());
3115         ResourceHandle::loadResourceSynchronously(newRequest, error, response, data);
3116     }
3117     
3118     sendRemainingDelegateMessages(identifier, response, data.size(), error);
3119 }
3120
3121 void FrameLoader::assignIdentifierToInitialRequest(unsigned long identifier, const ResourceRequest& clientRequest)
3122 {
3123     return m_client->assignIdentifierToInitialRequest(identifier, activeDocumentLoader(), clientRequest);
3124 }
3125
3126 void FrameLoader::willSendRequest(ResourceLoader* loader, ResourceRequest& clientRequest, const ResourceResponse& redirectResponse)
3127 {
3128     applyUserAgent(clientRequest);
3129     m_client->dispatchWillSendRequest(loader->documentLoader(), loader->identifier(), clientRequest, redirectResponse);
3130 }
3131
3132 void FrameLoader::didReceiveResponse(ResourceLoader* loader, const ResourceResponse& r)
3133 {
3134     activeDocumentLoader()->addResponse(r);
3135     
3136     if (m_frame->page())
3137         m_frame->page()->progress()->incrementProgress(loader->identifier(), r);
3138     m_client->dispatchDidReceiveResponse(loader->documentLoader(), loader->identifier(), r);
3139 }
3140
3141 void FrameLoader::didReceiveData(ResourceLoader* loader, const char* data, int length, int lengthReceived)
3142 {
3143     if (m_frame->page())
3144         m_frame->page()->progress()->incrementProgress(loader->identifier(), data, length);
3145     m_client->dispatchDidReceiveContentLength(loader->documentLoader(), loader->identifier(), lengthReceived);
3146 }
3147
3148 void FrameLoader::didFailToLoad(ResourceLoader* loader, const ResourceError& error)
3149 {
3150     if (m_frame->page())
3151         m_frame->page()->progress()->completeProgress(loader->identifier());
3152     if (!error.isNull())
3153         m_client->dispatchDidFailLoading(loader->documentLoader(), loader->identifier(), error);
3154 }
3155
3156 const ResourceRequest& FrameLoader::originalRequest() const
3157 {
3158     return activeDocumentLoader()->originalRequestCopy();
3159 }
3160
3161 void FrameLoader::receivedMainResourceError(const ResourceError& error, bool isComplete)
3162 {
3163     // Retain because the stop may release the last reference to it.
3164     RefPtr<Frame> protect(m_frame);
3165
3166     RefPtr<DocumentLoader> loader = activeDocumentLoader();
3167     
3168     if (isComplete) {
3169         // FIXME: Don't want to do this if an entirely new load is going, so should check
3170         // that both data sources on the frame are either this or nil.
3171         stop();
3172         if (m_client->shouldFallBack(error))
3173             handleFallbackContent();
3174     }
3175     
3176     if (m_state == FrameStateProvisional) {
3177         KURL failedURL = m_provisionalDocumentLoader->originalRequestCopy().url();
3178         didNotOpenURL(failedURL);
3179             
3180         // We might have made a page cache item, but now we're bailing out due to an error before we ever
3181         // transitioned to the new page (before WebFrameState == commit).  The goal here is to restore any state
3182         // so that the existing view (that wenever got far enough to replace) can continue being used.
3183         m_frame->document()->setInPageCache(false);
3184         invalidateCurrentItemCachedPage();
3185         
3186         // Call clientRedirectCancelledOrFinished here so that the frame load delegate is notified that the redirect's
3187         // status has changed, if there was a redirect. The frame load delegate may have saved some state about
3188         // the redirect in its -webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:. Since we are definitely
3189         // not going to use this provisional resource, as it was cancelled, notify the frame load delegate that the redirect
3190         // has ended.
3191         if (m_sentRedirectNotification)
3192             clientRedirectCancelledOrFinished(false);
3193     }
3194     
3195     
3196     loader->mainReceivedError(error, isComplete);
3197 }
3198
3199 void FrameLoader::callContinueFragmentScrollAfterNavigationPolicy(void* argument,
3200     const ResourceRequest& request, PassRefPtr<FormState>, bool shouldContinue)
3201 {
3202     FrameLoader* loader = static_cast<FrameLoader*>(argument);
3203     loader->continueFragmentScrollAfterNavigationPolicy(request, shouldContinue);
3204 }
3205
3206 void FrameLoader::continueFragmentScrollAfterNavigationPolicy(const ResourceRequest& request, bool shouldContinue)
3207 {
3208     bool isRedirect = m_quickRedirectComing;
3209     m_quickRedirectComing = false;
3210
3211     if (!shouldContinue)
3212         return;
3213
3214     KURL URL = request.url();
3215     
3216     m_documentLoader->replaceRequestURLForAnchorScroll(URL);
3217     if (!isRedirect && !shouldTreatURLAsSameAsCurrent(URL)) {
3218         // NB: must happen after _setURL, since we add based on the current request.
3219         // Must also happen before we openURL and displace the scroll position, since
3220         // adding the BF item will save away scroll state.
3221         
3222         // NB2:  If we were loading a long, slow doc, and the user anchor nav'ed before
3223         // it was done, currItem is now set the that slow doc, and prevItem is whatever was
3224         // before it.  Adding the b/f item will bump the slow doc down to prevItem, even
3225         // though its load is not yet done.  I think this all works out OK, for one because
3226         // we have already saved away the scroll and doc state for the long slow load,
3227         // but it's not an obvious case.
3228
3229         addHistoryItemForFragmentScroll();
3230     }
3231     
3232     scrollToAnchor(URL);
3233     
3234     if (!isRedirect)
3235         // This will clear previousItem from the rest of the frame tree that didn't
3236         // doing any loading. We need to make a pass on this now, since for anchor nav
3237         // we'll not go through a real load and reach Completed state.
3238         checkLoadComplete();
3239  
3240     dispatchDidChangeLocationWithinPage();
3241     m_client->didFinishLoad();
3242 }
3243
3244 void FrameLoader::opened()
3245 {
3246     if (m_loadType == FrameLoadTypeStandard && m_documentLoader->isClientRedirect())
3247         updateHistoryForClientRedirect();
3248
3249     if (m_documentLoader->isLoadingFromCachedPage()) {
3250         m_frame->document()->didRestoreFromCache();
3251         
3252         // Force a layout to update view size and thereby update scrollbars.
3253         m_client->forceLayout();
3254
3255         const ResponseVector& responses = m_documentLoader->responses();
3256         size_t count = responses.size();
3257         for (size_t i = 0; i < count; i++) {
3258             const ResourceResponse& response = responses[i];
3259             // FIXME: If the WebKit client changes or cancels the request, this is not respected.
3260             ResourceError error;
3261             unsigned long identifier;
3262             ResourceRequest request(response.url());
3263             requestFromDelegate(request, identifier, error);
3264             sendRemainingDelegateMessages(identifier, response, response.expectedContentLength(), error);
3265         }
3266         
3267         m_client->loadedFromCachedPage();
3268
3269         m_documentLoader->setPrimaryLoadComplete(true);
3270
3271         // FIXME: Why only this frame and not parent frames?
3272         checkLoadCompleteForThisFrame();
3273     }
3274 }
3275
3276 void FrameLoader::checkNewWindowPolicy(const NavigationAction& action, const ResourceRequest& request,
3277     PassRefPtr<FormState> formState, const String& frameName)
3278 {
3279     m_policyCheck.set(request, formState, frameName,
3280         callContinueLoadAfterNewWindowPolicy, this);
3281     m_client->dispatchDecidePolicyForNewWindowAction(&FrameLoader::continueAfterNewWindowPolicy,
3282         action, request, frameName);
3283 }
3284
3285 void FrameLoader::continueAfterNewWindowPolicy(PolicyAction policy)
3286 {
3287     PolicyCheck check = m_policyCheck;
3288     m_policyCheck.clear();
3289
3290     switch (policy) {
3291         case PolicyIgnore:
3292             check.clearRequest();
3293             break;
3294         case PolicyDownload:
3295             m_client->startDownload(check.request());
3296             check.clearRequest();
3297             break;
3298         case PolicyUse:
3299             break;
3300     }
3301
3302     check.call(policy == PolicyUse);
3303 }
3304
3305 void FrameLoader::checkNavigationPolicy(const ResourceRequest& request, DocumentLoader* loader,
3306     PassRefPtr<FormState> formState, NavigationPolicyDecisionFunction function, void* argument)
3307 {
3308     NavigationAction action = loader->triggeringAction();
3309     if (action.isEmpty()) {
3310         action = NavigationAction(request.url(), NavigationTypeOther);
3311         loader->setTriggeringAction(action);
3312     }
3313         
3314     // Don't ask more than once for the same request or if we are loading an empty URL.
3315     // This avoids confusion on the part of the client.
3316     if (request == loader->lastCheckedRequest() || (!request.isNull() && request.url().isEmpty())) {
3317         function(argument, request, 0, true);
3318         return;
3319     }
3320     
3321     // We are always willing to show alternate content for unreachable URLs;
3322     // treat it like a reload so it maintains the right state for b/f list.
3323     if (loader->substituteData().isValid() && !loader->substituteData().failingURL().isEmpty()) {
3324         if (isBackForwardLoadType(m_policyLoadType))
3325             m_policyLoadType = FrameLoadTypeReload;
3326         function(argument, request, 0, true);
3327         return;
3328     }
3329     
3330     loader->setLastCheckedRequest(request);
3331
3332     m_policyCheck.set(request, formState, function, argument);
3333
3334     m_delegateIsDecidingNavigationPolicy = true;
3335     m_client->dispatchDecidePolicyForNavigationAction(&FrameLoader::continueAfterNavigationPolicy,
3336         action, request);
3337     m_delegateIsDecidingNavigationPolicy = false;
3338 }
3339
3340 void FrameLoader::continueAfterNavigationPolicy(PolicyAction policy)
3341 {
3342     PolicyCheck check = m_policyCheck;
3343     m_policyCheck.clear();
3344
3345     bool shouldContinue = policy == PolicyUse;
3346     
3347     switch (policy) {
3348         case PolicyIgnore:
3349             check.clearRequest();
3350             break;
3351         case PolicyDownload:
3352             m_client->startDownload(check.request());
3353             check.clearRequest();
3354             break;
3355         case PolicyUse: {
3356             ResourceRequest request(check.request());
3357             
3358             if (!m_client->canHandleRequest(request)) {
3359                 handleUnimplementablePolicy(m_client->cannotShowURLError(check.request()));
3360                 check.clearRequest();
3361                 shouldContinue = false;
3362             }
3363             break;
3364         }
3365     }
3366
3367     check.call(shouldContinue);
3368 }
3369
3370 void FrameLoader::callContinueLoadAfterNavigationPolicy(void* argument,
3371     const ResourceRequest& request, PassRefPtr<FormState> formState, bool shouldContinue)
3372 {
3373     FrameLoader* loader = static_cast<FrameLoader*>(argument);
3374     loader->continueLoadAfterNavigationPolicy(request, formState, shouldContinue);
3375 }
3376
3377 void FrameLoader::continueLoadAfterNavigationPolicy(const ResourceRequest& request, PassRefPtr<FormState> formState, bool shouldContinue)
3378 {
3379     // If we loaded an alternate page to replace an unreachableURL, we'll get in here with a
3380     // nil policyDataSource because loading the alternate page will have passed
3381     // through this method already, nested; otherwise, policyDataSource should still be set.
3382     ASSERT(m_policyDocumentLoader || !m_provisionalDocumentLoader->unreachableURL().isEmpty());
3383
3384     bool isTargetItem = m_provisionalHistoryItem ? m_provisionalHistoryItem->isTargetItem() : false;
3385
3386     // Two reasons we can't continue:
3387     //    1) Navigation policy delegate said we can't so request is nil. A primary case of this 
3388     //       is the user responding Cancel to the form repost nag sheet.
3389     //    2) User responded Cancel to an alert popped up by the before unload event handler.
3390     // The "before unload" event handler runs only for the main frame.
3391     bool canContinue = shouldContinue && (!isLoadingMainFrame() || m_frame->shouldClose());
3392
3393     if (!canContinue) {
3394         // If we were waiting for a quick redirect, but the policy delegate decided to ignore it, then we 
3395         // need to report that the client redirect was cancelled.
3396         if (m_quickRedirectComing)
3397             clientRedirectCancelledOrFinished(false);
3398
3399         setPolicyDocumentLoader(0);
3400
3401         // If the navigation request came from the back/forward menu, and we punt on it, we have the 
3402         // problem that we have optimistically moved the b/f cursor already, so move it back.  For sanity, 
3403         // we only do this when punting a navigation for the target frame or top-level frame.  
3404         if ((isTargetItem || isLoadingMainFrame()) && isBackForwardLoadType(m_policyLoadType) && m_frame->page()) {
3405             Frame* mainFrame = m_frame->page()->mainFrame();
3406             if (HistoryItem* resetItem = mainFrame->loader()->m_currentHistoryItem.get())
3407                 m_frame->page()->backForwardList()->goToItem(resetItem);
3408         }
3409         return;
3410     }
3411
3412     FrameLoadType type = m_policyLoadType;
3413     stopAllLoaders();
3414     setProvisionalDocumentLoader(m_policyDocumentLoader.get());
3415     m_loadType = type;
3416     setState(FrameStateProvisional);
3417
3418     setPolicyDocumentLoader(0);
3419
3420     if (isBackForwardLoadType(type) && loadProvisionalItemFromCachedPage())
3421         return;
3422
3423     if (formState)
3424         m_client->dispatchWillSubmitForm(&FrameLoader::continueLoadAfterWillSubmitForm, formState);
3425     else
3426         continueLoadAfterWillSubmitForm();
3427 }
3428
3429
3430 void FrameLoader::callContinueLoadAfterNewWindowPolicy(void* argument,
3431     const ResourceRequest& request, PassRefPtr<FormState> formState, const String& frameName, bool shouldContinue)
3432 {
3433     FrameLoader* loader = static_cast<FrameLoader*>(argument);
3434     loader->continueLoadAfterNewWindowPolicy(request, formState, frameName, shouldContinue);
3435 }
3436
3437 void FrameLoader::continueLoadAfterNewWindowPolicy(const ResourceRequest& request,
3438     PassRefPtr<FormState> formState, const String& frameName, bool shouldContinue)
3439 {
3440     if (!shouldContinue)
3441         return;
3442
3443     RefPtr<Frame> frame = m_frame;
3444     RefPtr<Frame> mainFrame = m_client->dispatchCreatePage();
3445     if (!mainFrame)
3446         return;
3447
3448     if (frameName != "_blank")
3449         mainFrame->tree()->setName(frameName);
3450
3451     mainFrame->loader()->setOpenedByDOM();
3452     mainFrame->loader()->m_client->dispatchShow();
3453     mainFrame->loader()->setOpener(frame.get());
3454     mainFrame->loader()->load(request, NavigationAction(), FrameLoadTypeStandard, formState);
3455 }
3456
3457 void FrameLoader::sendRemainingDelegateMessages(unsigned long identifier, const ResourceResponse& response, unsigned length, const ResourceError& error)
3458 {    
3459     if (!response.isNull())
3460         m_client->dispatchDidReceiveResponse(m_documentLoader.get(), identifier, response);
3461     
3462     if (length > 0)
3463         m_client->dispatchDidReceiveContentLength(m_documentLoader.get(), identifier, length);
3464     
3465     if (error.isNull())
3466         m_client->dispatchDidFinishLoading(m_documentLoader.get(), identifier);
3467     else
3468         m_client->dispatchDidFailLoading(m_documentLoader.get(), identifier, error);
3469 }
3470
3471 void FrameLoader::requestFromDelegate(ResourceRequest& request, unsigned long& identifier, ResourceError& error)
3472 {
3473     ASSERT(!request.isNull());
3474
3475     identifier = m_frame->page()->progress()->createUniqueIdentifier();
3476     m_client->assignIdentifierToInitialRequest(identifier, m_documentLoader.get(), request);
3477
3478     ResourceRequest newRequest(request);
3479     m_client->dispatchWillSendRequest(m_documentLoader.get(), identifier, newRequest, ResourceResponse());
3480
3481     if (newRequest.isNull())
3482         error = m_client->cancelledError(request);
3483     else
3484         error = ResourceError();
3485
3486     request = newRequest;
3487 }
3488
3489 void FrameLoader::loadedResourceFromMemoryCache(const ResourceRequest& request, const ResourceResponse& response, int length)
3490 {
3491     if (m_client->dispatchDidLoadResourceFromMemoryCache(m_documentLoader.get(), request, response, length))
3492         return;
3493
3494     unsigned long identifier;
3495     ResourceError error;
3496     ResourceRequest r(request);
3497     requestFromDelegate(r, identifier, error);
3498     sendRemainingDelegateMessages(identifier, response, length, error);
3499 }
3500
3501 void FrameLoader::applyUserAgent(ResourceRequest& request)
3502 {
3503     String userAgent = client()->userAgent(request.url());
3504     ASSERT(!userAgent.isNull());
3505     request.setHTTPUserAgent(userAgent);
3506 }
3507
3508 bool FrameLoader::canGoBackOrForward(int distance) const
3509 {
3510     if (distance == 0)
3511         return true;
3512     if (distance > 0 && distance <= m_frame->page()->backForwardList()->forwardListCount())
3513         return true;
3514     if (distance < 0 && -distance <= m_frame->page()->backForwardList()->backListCount())
3515         return true;
3516     return false;
3517 }
3518
3519 int FrameLoader::getHistoryLength()
3520 {
3521     return m_frame->page()->backForwardList()->backListCount() + 1;
3522 }
3523
3524 KURL FrameLoader::historyURL(int distance)
3525 {
3526     BackForwardList *list = m_frame->page()->backForwardList();
3527     HistoryItem* item = list->itemAtIndex(distance);
3528     if (!item) {
3529         if (distance > 0) {
3530             int forwardListCount = list->forwardListCount();
3531             if (forwardListCount > 0)
3532                 item = list->itemAtIndex(forwardListCount);
3533         } else {
3534             int backListCount = list->backListCount();
3535             if (backListCount > 0)
3536                 item = list->itemAtIndex(-backListCount);
3537         }
3538     }
3539     if (item)
3540         return item->url();
3541
3542     return KURL();
3543 }
3544
3545 void FrameLoader::addHistoryItemForFragmentScroll()
3546 {
3547     addBackForwardItemClippedAtTarget(false);
3548 }
3549
3550 bool FrameLoader::loadProvisionalItemFromCachedPage()
3551 {
3552     if (!m_provisionalHistoryItem || !m_provisionalHistoryItem->cachedPage())
3553         return false;
3554
3555     if (!m_provisionalHistoryItem->cachedPage()->document())
3556         return false;
3557     
3558     provisionalDocumentLoader()->loadFromCachedPage(m_provisionalHistoryItem->cachedPage());
3559     return true;
3560 }
3561
3562 void FrameLoader::cachePageToHistoryItem(HistoryItem* item)
3563 {
3564     RefPtr<CachedPage> cachedPage = CachedPage::create(m_frame->page());
3565     cachedPage->setTimeStampToNow();
3566     cachedPage->setDocumentLoader(documentLoader());
3567     m_client->saveDocumentViewToCachedPage(cachedPage.get());
3568
3569     item->setCachedPage(cachedPage);
3570
3571     LOG(PageCache, "WebCorePageCache: CachedPage %p created for HistoryItem %p (%s)", 
3572         m_currentHistoryItem->cachedPage(), m_currentHistoryItem.get(), 
3573         m_currentHistoryItem->urlString().ascii().data());
3574 }
3575
3576 bool FrameLoader::shouldTreatURLAsSameAsCurrent(const KURL& URL) const
3577 {
3578     if (!m_currentHistoryItem)
3579         return false;
3580     return URL == m_currentHistoryItem->url() || URL == m_currentHistoryItem->originalURL();
3581 }
3582
3583 PassRefPtr<HistoryItem> FrameLoader::createHistoryItem(bool useOriginal)
3584 {
3585     DocumentLoader* docLoader = documentLoader();
3586     
3587     KURL unreachableURL = docLoader ? docLoader->unreachableURL() : KURL();
3588     
3589     KURL url;
3590     KURL originalURL;
3591
3592     if (!unreachableURL.isEmpty()) {
3593         url = unreachableURL;
3594         originalURL = unreachableURL;
3595     } else {
3596         originalURL = docLoader ? docLoader->originalURL() : KURL();
3597         if (useOriginal)
3598             url = originalURL;
3599         else if (docLoader)
3600             url = docLoader->requestURL();                
3601     }
3602
3603     LOG(History, "WebCoreHistory: Creating item for %s", url.url().ascii());
3604     
3605     // Frames that have never successfully loaded any content
3606     // may have no URL at all. Currently our history code can't
3607     // deal with such things, so we nip that in the bud here.
3608     // Later we may want to learn to live with nil for URL.
3609     // See bug 3368236 and related bugs for more information.
3610     if (url.isEmpty()) 
3611         url = KURL("about:blank");
3612     if (originalURL.isEmpty())
3613         originalURL = KURL("about:blank");
3614     
3615     RefPtr<HistoryItem> item = new HistoryItem(url, m_frame->tree()->name(), m_frame->tree()->parent() ? m_frame->tree()->parent()->tree()->name() : "", docLoader ? docLoader->title() : "");
3616     item->setOriginalURLString(originalURL.url());
3617     
3618     // Save form state if this is a POST
3619     if (docLoader) {
3620         if (useOriginal)
3621             item->setFormInfoFromRequest(docLoader->originalRequest());
3622         else
3623             item->setFormInfoFromRequest(docLoader->request());
3624     }
3625     
3626     // Set the item for which we will save document state
3627     m_previousHistoryItem = m_currentHistoryItem;
3628     m_currentHistoryItem = item;
3629     
3630     return item.release();
3631 }
3632
3633 void FrameLoader::addBackForwardItemClippedAtTarget(bool doClip)
3634 {
3635     if (!documentLoader()->urlForHistory().isEmpty()) {
3636         Frame* mainFrame = m_frame->page()->mainFrame();
3637         ASSERT(mainFrame);
3638         RefPtr<HistoryItem> item = mainFrame->loader()->createHistoryItemTree(m_frame, doClip);
3639         LOG(BackForward, "WebCoreBackForward - Adding backforward item %p for frame %s", item.get(), documentLoader()->URL().url().ascii());
3640         ASSERT(m_frame->page());
3641         m_frame->page()->backForwardList()->addItem(item);
3642     }
3643 }
3644
3645 PassRefPtr<HistoryItem> FrameLoader::createHistoryItemTree(Frame* targetFrame, bool clipAtTarget)
3646 {
3647     RefPtr<HistoryItem> bfItem = createHistoryItem(m_frame->tree()->parent() ? true : false);
3648     if (m_previousHistoryItem)
3649         saveScrollPositionAndViewStateToItem(m_previousHistoryItem.get());
3650    &