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