5e8bf5e33e5d1b276316fe2dd0c09f585bfca191
[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() && m_client->canCachePage() && !m_currentHistoryItem->cachedPage()) {
1555         cachePageToHistoryItem(m_currentHistoryItem.get());
1556         purgePageCache();
1557     }
1558 }
1559
1560 bool FrameLoader::userGestureHint()
1561 {
1562     Frame* rootFrame = m_frame;
1563     while (rootFrame->tree()->parent())
1564         rootFrame = rootFrame->tree()->parent();
1565
1566     if (rootFrame->scriptProxy())
1567         return rootFrame->scriptProxy()->interpreter()->wasRunByUserGesture();
1568
1569     return true; // If JavaScript is disabled, a user gesture must have initiated the navigation
1570 }
1571
1572 void FrameLoader::didNotOpenURL(const KURL& URL)
1573 {
1574     if (m_submittedFormURL == URL)
1575         m_submittedFormURL = KURL();
1576 }
1577
1578 void FrameLoader::resetMultipleFormSubmissionProtection()
1579 {
1580     m_submittedFormURL = KURL();
1581 }
1582
1583 void FrameLoader::setEncoding(const String& name, bool userChosen)
1584 {
1585     if (!m_workingURL.isEmpty())
1586         receivedFirstData();
1587     m_encoding = name;
1588     m_encodingWasChosenByUser = userChosen;
1589 }
1590
1591 void FrameLoader::addData(const char* bytes, int length)
1592 {
1593     ASSERT(m_workingURL.isEmpty());
1594     ASSERT(m_frame->document());
1595     ASSERT(m_frame->document()->parsing());
1596     write(bytes, length);
1597 }
1598
1599 bool FrameLoader::canCachePage()
1600 {    
1601     // Cache the page, if possible.
1602     // Don't write to the cache if in the middle of a redirect, since we will want to
1603     // store the final page we end up on.
1604     // No point writing to the cache on a reload or loadSame, since we will just write
1605     // over it again when we leave that page.
1606     // FIXME: <rdar://problem/4886592> - We should work out the complexities of caching pages with frames as they
1607     // are the most interesting pages on the web, and often those that would benefit the most from caching!
1608     FrameLoadType loadType = this->loadType();
1609
1610     return m_documentLoader
1611         && m_documentLoader->mainDocumentError().isNull()
1612         && !m_frame->tree()->childCount()
1613         && !m_frame->tree()->parent()
1614         && !m_containsPlugIns
1615         && !m_URL.protocol().startsWith("https")
1616         && m_frame->document()
1617         && !m_frame->document()->applets()->length()
1618         && !m_frame->document()->hasWindowEventListener(unloadEvent)
1619         && m_frame->page() 
1620         && m_frame->page()->backForwardList()->pageCacheSize() != 0
1621         && m_currentHistoryItem
1622         && !isQuickRedirectComing()
1623         && loadType != FrameLoadTypeReload 
1624         && loadType != FrameLoadTypeReloadAllowingStaleData
1625         && loadType != FrameLoadTypeSame
1626         && !m_documentLoader->isLoadingInAPISense()
1627         && !m_documentLoader->isStopping();
1628 }
1629
1630 void FrameLoader::updatePolicyBaseURL()
1631 {
1632     if (m_frame->tree()->parent() && m_frame->tree()->parent()->document())
1633         setPolicyBaseURL(m_frame->tree()->parent()->document()->policyBaseURL());
1634     else
1635         setPolicyBaseURL(m_URL.url());
1636 }
1637
1638 void FrameLoader::setPolicyBaseURL(const String& s)
1639 {
1640     if (m_frame->document())
1641         m_frame->document()->setPolicyBaseURL(s);
1642     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
1643         child->loader()->setPolicyBaseURL(s);
1644 }
1645
1646 // This does the same kind of work that FrameLoader::openURL does, except it relies on the fact
1647 // that a higher level already checked that the URLs match and the scrolling is the right thing to do.
1648 void FrameLoader::scrollToAnchor(const KURL& URL)
1649 {
1650     m_URL = URL;
1651     started();
1652
1653     gotoAnchor();
1654
1655     // It's important to model this as a load that starts and immediately finishes.
1656     // Otherwise, the parent frame may think we never finished loading.
1657     m_isComplete = false;
1658     checkCompleted();
1659 }
1660
1661 bool FrameLoader::isComplete() const
1662 {
1663     return m_isComplete;
1664 }
1665
1666 bool FrameLoader::isLoadingMainResource() const
1667 {
1668     return m_isLoadingMainResource;
1669 }
1670
1671 KURL FrameLoader::url() const
1672 {
1673     return m_URL;
1674 }
1675
1676 void FrameLoader::scheduleRedirection(ScheduledRedirection* redirection)
1677 {
1678     stopRedirectionTimer();
1679     m_scheduledRedirection.set(redirection);
1680     if (m_isComplete)
1681         startRedirectionTimer();
1682 }
1683
1684 void FrameLoader::startRedirectionTimer()
1685 {
1686     ASSERT(m_scheduledRedirection);
1687
1688     m_redirectionTimer.stop();
1689     m_redirectionTimer.startOneShot(m_scheduledRedirection->delay);
1690
1691     switch (m_scheduledRedirection->type) {
1692         case ScheduledRedirection::redirection:
1693         case ScheduledRedirection::locationChange:
1694         case ScheduledRedirection::locationChangeDuringLoad:
1695             clientRedirected(m_scheduledRedirection->URL.deprecatedString(),
1696                 m_scheduledRedirection->delay,
1697                 currentTime() + m_redirectionTimer.nextFireInterval(),
1698                 m_scheduledRedirection->lockHistory,
1699                 m_isExecutingJavaScriptFormAction);
1700             return;
1701         case ScheduledRedirection::historyNavigation:
1702             // Don't report history navigations.
1703             return;
1704     }
1705     ASSERT_NOT_REACHED();
1706 }
1707
1708 void FrameLoader::stopRedirectionTimer()
1709 {
1710     if (!m_redirectionTimer.isActive())
1711         return;
1712
1713     m_redirectionTimer.stop();
1714
1715     if (m_scheduledRedirection) {
1716         switch (m_scheduledRedirection->type) {
1717             case ScheduledRedirection::redirection:
1718             case ScheduledRedirection::locationChange:
1719             case ScheduledRedirection::locationChangeDuringLoad:
1720                 clientRedirectCancelledOrFinished(m_cancellingWithLoadInProgress);
1721                 return;
1722             case ScheduledRedirection::historyNavigation:
1723                 // Don't report history navigations.
1724                 return;
1725         }
1726         ASSERT_NOT_REACHED();
1727     }
1728 }
1729
1730 void FrameLoader::completed()
1731 {
1732     RefPtr<Frame> protect(m_frame);
1733     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
1734         child->loader()->parentCompleted();
1735     if (Frame* parent = m_frame->tree()->parent())
1736         parent->loader()->checkCompleted();
1737     submitFormAgain();
1738 }
1739
1740 void FrameLoader::started()
1741 {
1742     for (Frame* frame = m_frame; frame; frame = frame->tree()->parent())
1743         frame->loader()->m_isComplete = false;
1744 }
1745
1746 bool FrameLoader::containsPlugins() const 
1747
1748     return m_containsPlugIns;
1749 }
1750
1751 void FrameLoader::prepareForLoadStart()
1752 {
1753     if (m_frame->page())
1754         m_frame->page()->progress()->progressStarted(m_frame);
1755     m_client->dispatchDidStartProvisionalLoad();
1756 }
1757
1758 void FrameLoader::setupForReplace()
1759 {
1760     setState(FrameStateProvisional);
1761     m_provisionalDocumentLoader = m_documentLoader;
1762     m_documentLoader = 0;
1763     detachChildren();
1764 }
1765
1766 void FrameLoader::setupForReplaceByMIMEType(const String& newMIMEType)
1767 {
1768     activeDocumentLoader()->setupForReplaceByMIMEType(newMIMEType);
1769 }
1770
1771 void FrameLoader::finalSetupForReplace(DocumentLoader* loader)
1772 {
1773     m_client->clearUnarchivingState(loader);
1774 }
1775
1776 void FrameLoader::load(const KURL& URL, Event* event)
1777 {
1778     load(ResourceRequest(URL), true, event, 0, HashMap<String, String>());
1779 }
1780
1781 void FrameLoader::load(const FrameLoadRequest& request, bool userGesture, Event* event,
1782     HTMLFormElement* submitForm, const HashMap<String, String>& formValues)
1783 {
1784     String referrer;
1785     String argsReferrer = request.resourceRequest().httpReferrer();
1786     if (!argsReferrer.isEmpty())
1787         referrer = argsReferrer;
1788     else
1789         referrer = m_outgoingReferrer;
1790  
1791     bool hideReferrer;
1792     if (!canLoad(request.resourceRequest().url(), referrer, hideReferrer)) {
1793         FrameLoader::reportLocalLoadFailed(frame()->page(), request.resourceRequest().url().url());
1794         return;
1795     }
1796
1797     if (hideReferrer)
1798         referrer = String();
1799     
1800     Frame* targetFrame = m_frame->tree()->find(request.frameName());
1801     if (!canTarget(targetFrame))
1802         return;
1803         
1804     if (request.resourceRequest().httpMethod() != "POST") {
1805         FrameLoadType loadType;
1806         if (request.resourceRequest().cachePolicy() == ReloadIgnoringCacheData)
1807             loadType = FrameLoadTypeReload;
1808         else if (!userGesture)
1809             loadType = FrameLoadTypeInternal;
1810         else
1811             loadType = FrameLoadTypeStandard;    
1812     
1813         load(request.resourceRequest().url(), referrer, loadType, 
1814             request.frameName(), event, submitForm, formValues);
1815     } else
1816         post(request.resourceRequest().url(), referrer, request.frameName(), 
1817             request.resourceRequest().httpBody(), request.resourceRequest().httpContentType(), event, submitForm, formValues);
1818
1819     if (targetFrame && targetFrame != m_frame)
1820         targetFrame->page()->chrome()->focus();
1821 }
1822
1823 void FrameLoader::load(const KURL& URL, const String& referrer, FrameLoadType newLoadType,
1824     const String& frameName, Event* event, HTMLFormElement* form, const HashMap<String, String>& values)
1825 {
1826     bool isFormSubmission = !values.isEmpty();
1827     
1828     ResourceRequest request(URL);
1829     if (!referrer.isEmpty())
1830         request.setHTTPReferrer(referrer);
1831     addExtraFieldsToRequest(request, true, event || isFormSubmission);
1832     if (newLoadType == FrameLoadTypeReload)
1833         request.setCachePolicy(ReloadIgnoringCacheData);
1834
1835     ASSERT(newLoadType != FrameLoadTypeSame);
1836
1837     NavigationAction action(URL, newLoadType, isFormSubmission, event);
1838
1839     RefPtr<FormState> formState;
1840     if (form && !values.isEmpty())
1841         formState = FormState::create(form, values, m_frame);
1842     
1843     if (!frameName.isEmpty()) {
1844         if (Frame* targetFrame = m_frame->tree()->find(frameName))
1845             targetFrame->loader()->load(URL, referrer, newLoadType, String(), event, form, values);
1846         else
1847             checkNewWindowPolicy(action, request, formState.release(), frameName);
1848         return;
1849     }
1850
1851     RefPtr<DocumentLoader> oldDocumentLoader = m_documentLoader;
1852
1853     bool sameURL = shouldTreatURLAsSameAsCurrent(URL);
1854     
1855     // Make sure to do scroll to anchor processing even if the URL is
1856     // exactly the same so pages with '#' links and DHTML side effects
1857     // work properly.
1858     if (!isFormSubmission
1859         && newLoadType != FrameLoadTypeReload
1860         && newLoadType != FrameLoadTypeSame
1861         && !shouldReload(URL, url())
1862         // We don't want to just scroll if a link from within a
1863         // frameset is trying to reload the frameset into _top.
1864         && !m_frame->isFrameSet()) {
1865
1866         // Just do anchor navigation within the existing content.
1867         
1868         // We don't do this if we are submitting a form, explicitly reloading,
1869         // currently displaying a frameset, or if the new URL does not have a fragment.
1870         // These rules are based on what KHTML was doing in KHTMLPart::openURL.
1871         
1872         // FIXME: What about load types other than Standard and Reload?
1873         
1874         oldDocumentLoader->setTriggeringAction(action);
1875         stopPolicyCheck();
1876         checkNavigationPolicy(request, oldDocumentLoader.get(), formState.release(),
1877             callContinueFragmentScrollAfterNavigationPolicy, this);
1878     } else {
1879         // must grab this now, since this load may stop the previous load and clear this flag
1880         bool isRedirect = m_quickRedirectComing;
1881         load(request, action, newLoadType, formState.release());
1882         if (isRedirect) {
1883             m_quickRedirectComing = false;
1884             if (m_provisionalDocumentLoader)
1885                 m_provisionalDocumentLoader->setIsClientRedirect(true);
1886         } else if (sameURL)
1887             // Example of this case are sites that reload the same URL with a different cookie
1888             // driving the generated content, or a master frame with links that drive a target
1889             // frame, where the user has clicked on the same link repeatedly.
1890             m_loadType = FrameLoadTypeSame;
1891     }
1892 }
1893
1894 void FrameLoader::load(const ResourceRequest& request)
1895 {
1896     load(request, SubstituteData());
1897 }
1898
1899 void FrameLoader::load(const ResourceRequest& request, const SubstituteData& substituteData)
1900 {
1901     if (m_inStopAllLoaders)
1902         return;
1903         
1904     // FIXME: is this the right place to reset loadType? Perhaps this should be done after loading is finished or aborted.
1905     m_loadType = FrameLoadTypeStandard;
1906     load(m_client->createDocumentLoader(request, substituteData).get());
1907 }
1908
1909 void FrameLoader::load(const ResourceRequest& request, const String& frameName)
1910 {
1911     if (frameName.isEmpty()) {
1912         load(request);
1913         return;
1914     }
1915
1916     Frame* frame = m_frame->tree()->find(frameName);
1917     if (frame) {
1918         frame->loader()->load(request);
1919         return;
1920     }
1921
1922     checkNewWindowPolicy(NavigationAction(request.url(), NavigationTypeOther), request, 0, frameName);
1923 }
1924
1925 void FrameLoader::load(const ResourceRequest& request, const NavigationAction& action, FrameLoadType type, PassRefPtr<FormState> formState)
1926 {
1927     RefPtr<DocumentLoader> loader = m_client->createDocumentLoader(request, SubstituteData());
1928
1929     loader->setTriggeringAction(action);
1930     if (m_documentLoader)
1931         loader->setOverrideEncoding(m_documentLoader->overrideEncoding());
1932
1933     load(loader.get(), type, formState);
1934 }
1935
1936 void FrameLoader::load(DocumentLoader* newDocumentLoader)
1937 {
1938     ResourceRequest& r = newDocumentLoader->request();
1939     addExtraFieldsToRequest(r, true, false);
1940     FrameLoadType type;
1941
1942     if (shouldTreatURLAsSameAsCurrent(newDocumentLoader->originalRequest().url())) {
1943         r.setCachePolicy(ReloadIgnoringCacheData);
1944         type = FrameLoadTypeSame;
1945     } else
1946         type = FrameLoadTypeStandard;
1947
1948     if (m_documentLoader)
1949         newDocumentLoader->setOverrideEncoding(m_documentLoader->overrideEncoding());
1950     
1951     // When we loading alternate content for an unreachable URL that we're
1952     // visiting in the b/f list, we treat it as a reload so the b/f list 
1953     // is appropriately maintained.
1954     if (shouldReloadToHandleUnreachableURL(newDocumentLoader)) {
1955         ASSERT(type == FrameLoadTypeStandard);
1956         type = FrameLoadTypeReload;
1957     }
1958
1959     load(newDocumentLoader, type, 0);
1960 }
1961
1962 void FrameLoader::load(DocumentLoader* loader, FrameLoadType type, PassRefPtr<FormState> formState)
1963 {
1964     ASSERT(m_client->hasWebView());
1965
1966     // Unfortunately the view must be non-nil, this is ultimately due
1967     // to parser requiring a FrameView.  We should fix this dependency.
1968
1969     ASSERT(m_client->hasFrameView());
1970
1971     m_policyLoadType = type;
1972
1973     if (Frame* parent = m_frame->tree()->parent())
1974         loader->setOverrideEncoding(parent->loader()->documentLoader()->overrideEncoding());
1975
1976     stopPolicyCheck();
1977     setPolicyDocumentLoader(loader);
1978
1979     checkNavigationPolicy(loader->request(), loader, formState,
1980         callContinueLoadAfterNavigationPolicy, this);
1981 }
1982
1983 // FIXME: It would be nice if we could collapse these into one or two functions.
1984 bool FrameLoader::canLoad(const KURL& url, const String& referrer, bool& hideReferrer)
1985 {
1986     hideReferrer = shouldHideReferrer(url, referrer);
1987
1988     if (!shouldTreatURLAsLocal(url.url()))
1989         return true;
1990
1991     return shouldTreatURLAsLocal(referrer);
1992 }
1993
1994 bool FrameLoader::canLoad(const KURL& url, const Document* doc)
1995 {
1996     if (!shouldTreatURLAsLocal(url.url()))
1997         return true;
1998
1999     return doc && doc->isAllowedToLoadLocalResources();
2000 }
2001
2002 bool FrameLoader::canLoad(const CachedResource& resource, const Document* doc)
2003 {
2004     if (!resource.treatAsLocal())
2005         return true;
2006
2007     return doc && doc->isAllowedToLoadLocalResources();
2008 }
2009
2010 void FrameLoader::reportLocalLoadFailed(const Page* page, const String& url)
2011 {
2012     ASSERT(!url.isEmpty());
2013     if(page)
2014         page->chrome()->addMessageToConsole("Not allowed to load local resource: " + url, 0, String());
2015 }
2016
2017 bool FrameLoader::shouldHideReferrer(const KURL& url, const String& referrer)
2018 {
2019     bool referrerIsSecureURL = referrer.startsWith("https:", false);
2020     bool referrerIsWebURL = referrerIsSecureURL || referrer.startsWith("http:", false);
2021
2022     if (!referrerIsWebURL)
2023         return true;
2024
2025     if (!referrerIsSecureURL)
2026         return false;
2027
2028     bool URLIsSecureURL = url.url().startsWith("https:", false);
2029
2030     return !URLIsSecureURL;
2031 }
2032
2033 const ResourceRequest& FrameLoader::initialRequest() const
2034 {
2035     return activeDocumentLoader()->initialRequest();
2036 }
2037
2038 void FrameLoader::receivedData(const char* data, int length)
2039 {
2040     activeDocumentLoader()->receivedData(data, length);
2041 }
2042
2043 bool FrameLoader::willUseArchive(ResourceLoader* loader, const ResourceRequest& request, const KURL& originalURL) const
2044 {
2045     return m_client->willUseArchive(loader, request, originalURL);
2046 }
2047
2048 void FrameLoader::handleUnimplementablePolicy(const ResourceError& error)
2049 {
2050     m_delegateIsHandlingUnimplementablePolicy = true;
2051     m_client->dispatchUnableToImplementPolicy(error);
2052     m_delegateIsHandlingUnimplementablePolicy = false;
2053 }
2054
2055 void FrameLoader::cannotShowMIMEType(const ResourceResponse& response)
2056 {
2057     handleUnimplementablePolicy(m_client->cannotShowMIMETypeError(response));
2058 }
2059
2060 ResourceError FrameLoader::interruptionForPolicyChangeError(const ResourceRequest& request)
2061 {
2062     return m_client->interruptForPolicyChangeError(request);
2063 }
2064
2065 void FrameLoader::checkNavigationPolicy(const ResourceRequest& newRequest, NavigationPolicyDecisionFunction function, void* argument)
2066 {
2067     checkNavigationPolicy(newRequest, activeDocumentLoader(), 0, function, argument);
2068 }
2069
2070 void FrameLoader::checkContentPolicy(const String& MIMEType, ContentPolicyDecisionFunction function, void* argument)
2071 {
2072     ASSERT(activeDocumentLoader());
2073     
2074     // Always show content with valid substitute data.
2075     if (activeDocumentLoader()->substituteData().isValid()) {
2076         function(argument, PolicyUse);
2077         return;
2078     }
2079
2080     m_policyCheck.set(function, argument);
2081     m_client->dispatchDecidePolicyForMIMEType(&FrameLoader::continueAfterContentPolicy,
2082         MIMEType, activeDocumentLoader()->request());
2083 }
2084
2085 bool FrameLoader::shouldReloadToHandleUnreachableURL(DocumentLoader* docLoader)
2086 {
2087     KURL unreachableURL = docLoader->unreachableURL();
2088
2089     if (unreachableURL.isEmpty())
2090         return false;
2091
2092     if (!isBackForwardLoadType(m_policyLoadType))
2093         return false;
2094
2095     // We only treat unreachableURLs specially during the delegate callbacks
2096     // for provisional load errors and navigation policy decisions. The former
2097     // case handles well-formed URLs that can't be loaded, and the latter
2098     // case handles malformed URLs and unknown schemes. Loading alternate content
2099     // at other times behaves like a standard load.
2100     DocumentLoader* compareDocumentLoader = 0;
2101     if (m_delegateIsDecidingNavigationPolicy || m_delegateIsHandlingUnimplementablePolicy)
2102         compareDocumentLoader = m_policyDocumentLoader.get();
2103     else if (m_delegateIsHandlingProvisionalLoadError)
2104         compareDocumentLoader = m_provisionalDocumentLoader.get();
2105
2106     return compareDocumentLoader && unreachableURL == compareDocumentLoader->request().url();
2107 }
2108
2109 void FrameLoader::reloadAllowingStaleData(const String& encoding)
2110 {
2111     if (!m_documentLoader)
2112         return;
2113
2114     ResourceRequest request = m_documentLoader->request();
2115     KURL unreachableURL = m_documentLoader->unreachableURL();
2116     if (!unreachableURL.isEmpty())
2117         request.setURL(unreachableURL);
2118
2119     request.setCachePolicy(ReturnCacheDataElseLoad);
2120
2121     RefPtr<DocumentLoader> loader = m_client->createDocumentLoader(request, SubstituteData());
2122     setPolicyDocumentLoader(loader.get());
2123
2124     loader->setOverrideEncoding(encoding);
2125
2126     load(loader.get(), FrameLoadTypeReloadAllowingStaleData, 0);
2127 }
2128
2129 void FrameLoader::reload()
2130 {
2131     if (!m_documentLoader)
2132         return;
2133
2134     ResourceRequest& initialRequest = m_documentLoader->request();
2135     
2136     // If a window is created by javascript, its main frame can have an empty but non-nil URL.
2137     // Reloading in this case will lose the current contents (see 4151001).
2138     if (initialRequest.url().isEmpty())
2139         return;
2140
2141     // Replace error-page URL with the URL we were trying to reach.
2142     KURL unreachableURL = m_documentLoader->unreachableURL();
2143     if (!unreachableURL.isEmpty())
2144         initialRequest = ResourceRequest(unreachableURL);
2145     
2146     RefPtr<DocumentLoader> loader = m_client->createDocumentLoader(initialRequest, SubstituteData());
2147
2148     ResourceRequest& request = loader->request();
2149
2150     request.setCachePolicy(ReloadIgnoringCacheData);
2151     request.setHTTPHeaderField("Cache-Control", "max-age=0");
2152
2153     // If we're about to re-post, set up action so the application can warn the user.
2154     if (request.httpMethod() == "POST")
2155         loader->setTriggeringAction(NavigationAction(request.url(), NavigationTypeFormResubmitted));
2156
2157     loader->setOverrideEncoding(m_documentLoader->overrideEncoding());
2158     
2159     load(loader.get(), FrameLoadTypeReload, 0);
2160 }
2161
2162 bool FrameLoader::canTarget(Frame* target) const
2163 {
2164     // This method prevents this exploit:
2165     // <rdar://problem/3715785> multiple frame injection vulnerability reported by Secunia, affects almost all browsers
2166
2167     if (!target)
2168         return true;
2169
2170     // Allow with navigation within the same page/frameset.
2171     if (m_frame->page() == target->page())
2172         return true;
2173
2174     ASSERT(m_frame->document());
2175     String domain = m_frame->document()->domain();
2176     // Allow if the request is made from a local file.
2177     if (domain.isEmpty())
2178         return true;
2179     
2180     Frame* parent = target->tree()->parent();
2181     // Allow if target is an entire window.
2182     if (!parent)
2183         return true;
2184     
2185     String parentDomain;
2186     if (Document* parentDocument = parent->document())
2187         domain = parentDocument->domain();
2188     // Allow if the domain of the parent of the targeted frame equals this domain.
2189     return equalIgnoringCase(parentDomain, domain);
2190 }
2191
2192 void FrameLoader::stopLoadingSubframes()
2193 {
2194     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
2195         child->loader()->stopAllLoaders();
2196 }
2197
2198 void FrameLoader::stopAllLoaders()
2199 {
2200     // If this method is called from within this method, infinite recursion can occur (3442218). Avoid this.
2201     if (m_inStopAllLoaders)
2202         return;
2203
2204     m_inStopAllLoaders = true;
2205
2206     stopPolicyCheck();
2207
2208     stopLoadingSubframes();
2209     if (m_provisionalDocumentLoader)
2210         m_provisionalDocumentLoader->stopLoading();
2211     if (m_documentLoader)
2212         m_documentLoader->stopLoading();
2213     setProvisionalDocumentLoader(0);
2214     m_client->clearArchivedResources();
2215
2216     m_inStopAllLoaders = false;    
2217 }
2218
2219 void FrameLoader::stopForUserCancel()
2220 {
2221     stopAllLoaders();
2222     if (m_frame->page())
2223         checkLoadComplete();
2224 }
2225
2226 void FrameLoader::cancelPendingArchiveLoad(ResourceLoader* loader)
2227 {
2228     m_client->cancelPendingArchiveLoad(loader);
2229 }
2230
2231 DocumentLoader* FrameLoader::activeDocumentLoader() const
2232 {
2233     if (m_state == FrameStateProvisional)
2234         return m_provisionalDocumentLoader.get();
2235     return m_documentLoader.get();
2236 }
2237
2238 bool FrameLoader::isLoading() const
2239 {
2240     DocumentLoader* docLoader = activeDocumentLoader();
2241     if (!docLoader)
2242         return false;
2243     return docLoader->isLoadingMainResource() || docLoader->isLoadingSubresources() || docLoader->isLoadingPlugIns();
2244 }
2245
2246 void FrameLoader::setDocumentLoader(DocumentLoader* loader)
2247 {
2248     if (!loader && !m_documentLoader)
2249         return;
2250     
2251     ASSERT(loader != m_documentLoader);
2252     ASSERT(!loader || loader->frameLoader() == this);
2253
2254     m_client->prepareForDataSourceReplacement();
2255     detachChildren();
2256     if (m_documentLoader)
2257         m_documentLoader->detachFromFrame();
2258
2259     m_documentLoader = loader;
2260 }
2261
2262 DocumentLoader* FrameLoader::documentLoader() const
2263 {
2264     return m_documentLoader.get();
2265 }
2266
2267 void FrameLoader::setPolicyDocumentLoader(DocumentLoader* loader)
2268 {
2269     if (m_policyDocumentLoader == loader)
2270         return;
2271
2272     ASSERT(m_frame);
2273     if (loader)
2274         loader->setFrame(m_frame);
2275     if (m_policyDocumentLoader
2276             && m_policyDocumentLoader != m_provisionalDocumentLoader
2277             && m_policyDocumentLoader != m_documentLoader)
2278         m_policyDocumentLoader->detachFromFrame();
2279
2280     m_policyDocumentLoader = loader;
2281 }
2282    
2283 DocumentLoader* FrameLoader::provisionalDocumentLoader()
2284 {
2285     return m_provisionalDocumentLoader.get();
2286 }
2287
2288 void FrameLoader::setProvisionalDocumentLoader(DocumentLoader* loader)
2289 {
2290     ASSERT(!loader || !m_provisionalDocumentLoader);
2291     ASSERT(!loader || loader->frameLoader() == this);
2292
2293     if (m_provisionalDocumentLoader && m_provisionalDocumentLoader != m_documentLoader)
2294         m_provisionalDocumentLoader->detachFromFrame();
2295
2296     m_provisionalDocumentLoader = loader;
2297 }
2298
2299 FrameState FrameLoader::state() const
2300 {
2301     return m_state;
2302 }
2303
2304 double FrameLoader::timeOfLastCompletedLoad()
2305 {
2306     return storedTimeOfLastCompletedLoad;
2307 }
2308
2309 void FrameLoader::setState(FrameState newState)
2310 {    
2311     m_state = newState;
2312     
2313     if (newState == FrameStateProvisional)
2314         provisionalLoadStarted();
2315     else if (newState == FrameStateComplete) {
2316         frameLoadCompleted();
2317         storedTimeOfLastCompletedLoad = currentTime();
2318         if (m_documentLoader)
2319             m_documentLoader->stopRecordingResponses();
2320     }
2321 }
2322
2323 void FrameLoader::clearProvisionalLoad()
2324 {
2325     setProvisionalDocumentLoader(0);
2326     if (m_frame->page())
2327         m_frame->page()->progress()->progressCompleted(m_frame);
2328     setState(FrameStateComplete);
2329 }
2330
2331 void FrameLoader::markLoadComplete()
2332 {
2333     setState(FrameStateComplete);
2334 }
2335
2336 void FrameLoader::commitProvisionalLoad(PassRefPtr<CachedPage> prpCachedPage)
2337 {
2338     RefPtr<CachedPage> cachedPage = prpCachedPage;
2339     RefPtr<DocumentLoader> pdl = m_provisionalDocumentLoader;
2340     
2341     if (m_loadType != FrameLoadTypeReplace)
2342         closeOldDataSources();
2343     
2344     if (!cachedPage)
2345         m_client->makeRepresentation(pdl.get());
2346     
2347     transitionToCommitted(cachedPage);
2348     
2349     // Call clientRedirectCancelledOrFinished() here so that the frame load delegate is notified that the redirect's
2350     // status has changed, if there was a redirect.  The frame load delegate may have saved some state about
2351     // the redirect in its -webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:.  Since we are
2352     // just about to commit a new page, there cannot possibly be a pending redirect at this point.
2353     if (m_sentRedirectNotification)
2354         clientRedirectCancelledOrFinished(false);
2355     
2356     if (cachedPage && cachedPage->document()) {
2357         open(*cachedPage);
2358         cachedPage->clear();
2359     } else {        
2360         KURL url = pdl->substituteData().responseURL();
2361         if (url.isEmpty())
2362             url = pdl->URL();
2363         if (url.isEmpty())
2364             url = pdl->responseURL();
2365         if (url.isEmpty())
2366             url = "about:blank";
2367
2368         didOpenURL(url);
2369     }
2370     opened();
2371 }
2372
2373 void FrameLoader::transitionToCommitted(PassRefPtr<CachedPage> cachedPage)
2374 {
2375     ASSERT(m_client->hasWebView());
2376     ASSERT(m_state == FrameStateProvisional);
2377
2378     if (m_state != FrameStateProvisional)
2379         return;
2380
2381     m_client->setCopiesOnScroll();
2382     updateHistoryForCommit();
2383
2384     // The call to closeURL() invokes the unload event handler, which can execute arbitrary
2385     // JavaScript. If the script initiates a new load, we need to abandon the current load,
2386     // or the two will stomp each other.
2387     DocumentLoader* pdl = m_provisionalDocumentLoader.get();
2388     if (m_documentLoader)
2389         closeURL();
2390     if (pdl != m_provisionalDocumentLoader)
2391         return;
2392
2393     // Nothing else can interupt this commit - set the Provisional->Committed transition in stone
2394     if (m_documentLoader)
2395         m_documentLoader->stopLoadingSubresources();
2396     if (m_documentLoader)
2397         m_documentLoader->stopLoadingPlugIns();
2398
2399     setDocumentLoader(m_provisionalDocumentLoader.get());
2400     setProvisionalDocumentLoader(0);
2401     setState(FrameStateCommittedPage);
2402
2403     // Handle adding the URL to the back/forward list.
2404     DocumentLoader* dl = m_documentLoader.get();
2405     String ptitle = dl->title();
2406
2407     switch (m_loadType) {
2408         case FrameLoadTypeForward:
2409         case FrameLoadTypeBack:
2410         case FrameLoadTypeIndexedBackForward:
2411             if (m_frame->page()->backForwardList()) {
2412                 updateHistoryForBackForwardNavigation();
2413
2414                 // Create a document view for this document, or used the cached view.
2415                 if (cachedPage)
2416                     m_client->setDocumentViewFromCachedPage(cachedPage.get());
2417                 else
2418                     m_client->makeDocumentView();
2419             }
2420             break;
2421
2422         case FrameLoadTypeReload:
2423         case FrameLoadTypeSame:
2424         case FrameLoadTypeReplace:
2425             updateHistoryForReload();
2426             m_client->makeDocumentView();
2427             break;
2428
2429         // FIXME - just get rid of this case, and merge FrameLoadTypeReloadAllowingStaleData with the above case
2430         case FrameLoadTypeReloadAllowingStaleData:
2431             m_client->makeDocumentView();
2432             break;
2433
2434         case FrameLoadTypeStandard:
2435             updateHistoryForStandardLoad();
2436             m_client->makeDocumentView();
2437             break;
2438
2439         case FrameLoadTypeInternal:
2440             updateHistoryForInternalLoad();
2441             m_client->makeDocumentView();
2442             break;
2443
2444         // FIXME Remove this check when dummy ds is removed (whatever "dummy ds" is).
2445         // An exception should be thrown if we're in the FrameLoadTypeUninitialized state.
2446         default:
2447             ASSERT_NOT_REACHED();
2448     }
2449
2450     m_responseMIMEType = dl->responseMIMEType();
2451
2452     // Tell the client we've committed this URL.
2453     ASSERT(m_client->hasFrameView());
2454
2455     if (m_creatingInitialEmptyDocument)
2456         return;
2457
2458     m_client->dispatchDidCommitLoad();
2459     
2460     // If we have a title let the WebView know about it.
2461     if (!ptitle.isNull())
2462         m_client->dispatchDidReceiveTitle(ptitle);
2463 }
2464
2465 bool FrameLoader::privateBrowsingEnabled() const
2466 {
2467     return m_client->privateBrowsingEnabled();
2468 }
2469
2470 void FrameLoader::clientRedirectCancelledOrFinished(bool cancelWithLoadInProgress)
2471 {
2472     // Note that -webView:didCancelClientRedirectForFrame: is called on the frame load delegate even if
2473     // the redirect succeeded.  We should either rename this API, or add a new method, like
2474     // -webView:didFinishClientRedirectForFrame:
2475     m_client->dispatchDidCancelClientRedirect();
2476
2477     if (!cancelWithLoadInProgress)
2478         m_quickRedirectComing = false;
2479
2480     m_sentRedirectNotification = false;
2481 }
2482
2483 void FrameLoader::clientRedirected(const KURL& URL, double seconds, double fireDate, bool lockHistory, bool isJavaScriptFormAction)
2484 {
2485     m_client->dispatchWillPerformClientRedirect(URL, seconds, fireDate);
2486     
2487     // Remember that we sent a redirect notification to the frame load delegate so that when we commit
2488     // the next provisional load, we can send a corresponding -webView:didCancelClientRedirectForFrame:
2489     m_sentRedirectNotification = true;
2490     
2491     // If a "quick" redirect comes in an, we set a special mode so we treat the next
2492     // load as part of the same navigation. If we don't have a document loader, we have
2493     // no "original" load on which to base a redirect, so we treat the redirect as a normal load.
2494     m_quickRedirectComing = lockHistory && m_documentLoader && !isJavaScriptFormAction;
2495 }
2496
2497 bool FrameLoader::shouldReload(const KURL& currentURL, const KURL& destinationURL)
2498 {
2499     // This function implements the rule: "Don't reload if navigating by fragment within
2500     // the same URL, but do reload if going to a new URL or to the same URL with no
2501     // fragment identifier at all."
2502     if (!currentURL.hasRef() && !destinationURL.hasRef())
2503         return true;
2504     return !equalIgnoringRef(currentURL, destinationURL);
2505 }
2506
2507 void FrameLoader::closeOldDataSources()
2508 {
2509     // FIXME: Is it important for this traversal to be postorder instead of preorder?
2510     // If so, add helpers for postorder traversal, and use them. If not, then lets not
2511     // use a recursive algorithm here.
2512     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
2513         child->loader()->closeOldDataSources();
2514     
2515     if (m_documentLoader)
2516         m_client->dispatchWillClose();
2517
2518     m_client->setMainFrameDocumentReady(false); // stop giving out the actual DOMDocument to observers
2519 }
2520
2521 void FrameLoader::open(CachedPage& cachedPage)
2522 {
2523     ASSERT(m_frame->page()->mainFrame() == m_frame);
2524
2525     cancelRedirection();
2526
2527     // We still have to close the previous part page.
2528     closeURL();
2529
2530     m_isComplete = false;
2531     
2532     // Don't re-emit the load event.
2533     m_wasLoadEventEmitted = true;
2534     
2535     // Delete old status bar messages (if it _was_ activated on last URL).
2536     if (m_frame->settings()->isJavaScriptEnabled()) {
2537         m_frame->setJSStatusBarText(String());
2538         m_frame->setJSDefaultStatusBarText(String());
2539     }
2540
2541     KURL URL = cachedPage.URL();
2542
2543     if (URL.protocol().startsWith("http") && !URL.host().isEmpty() && URL.path().isEmpty())
2544         URL.setPath("/");
2545     
2546     m_URL = URL;
2547     m_workingURL = URL;
2548
2549     started();
2550
2551     clear();
2552
2553     Document* document = cachedPage.document();
2554     ASSERT(document);
2555     document->setInPageCache(false);
2556
2557     m_needsClear = true;
2558     m_isComplete = false;
2559     m_wasLoadEventEmitted = false;
2560     m_outgoingReferrer = URL.url();
2561
2562     FrameView* view = cachedPage.view();
2563     if (view)
2564         view->setWasScrolledByUser(false);
2565     m_frame->setView(view);
2566     
2567     m_frame->setDocument(document);
2568     m_decoder = document->decoder();
2569
2570     updatePolicyBaseURL();
2571
2572     cachedPage.restore(m_frame->page());
2573
2574     checkCompleted();
2575 }
2576
2577 bool FrameLoader::isStopping() const
2578 {
2579     return activeDocumentLoader()->isStopping();
2580 }
2581
2582 void FrameLoader::finishedLoading()
2583 {
2584     // Retain because the stop may release the last reference to it.
2585     RefPtr<Frame> protect(m_frame);
2586
2587     RefPtr<DocumentLoader> dl = activeDocumentLoader();
2588     dl->finishedLoading();
2589     if (!dl->mainDocumentError().isNull() || !dl->frameLoader())
2590         return;
2591     dl->setPrimaryLoadComplete(true);
2592     m_client->dispatchDidLoadMainResource(dl.get());
2593     checkLoadComplete();
2594 }
2595
2596 KURL FrameLoader::URL() const
2597 {
2598     return activeDocumentLoader()->URL();
2599 }
2600
2601 bool FrameLoader::isArchiveLoadPending(ResourceLoader* loader) const
2602 {
2603     return m_client->isArchiveLoadPending(loader);
2604 }
2605
2606 bool FrameLoader::isHostedByObjectElement() const
2607 {
2608     HTMLFrameOwnerElement* owner = m_frame->ownerElement();
2609     return owner && owner->hasTagName(objectTag);
2610 }
2611
2612 bool FrameLoader::isLoadingMainFrame() const
2613 {
2614     Page* page = m_frame->page();
2615     return page && m_frame == page->mainFrame();
2616 }
2617
2618 bool FrameLoader::canShowMIMEType(const String& MIMEType) const
2619 {
2620     return m_client->canShowMIMEType(MIMEType);
2621 }
2622
2623 bool FrameLoader::representationExistsForURLScheme(const String& URLScheme)
2624 {
2625     return m_client->representationExistsForURLScheme(URLScheme);
2626 }
2627
2628 String FrameLoader::generatedMIMETypeForURLScheme(const String& URLScheme)
2629 {
2630     return m_client->generatedMIMETypeForURLScheme(URLScheme);
2631 }
2632
2633 void FrameLoader::cancelContentPolicyCheck()
2634 {
2635     m_client->cancelPolicyCheck();
2636     m_policyCheck.clear();
2637 }
2638
2639 void FrameLoader::didReceiveServerRedirectForProvisionalLoadForFrame()
2640 {
2641     m_client->dispatchDidReceiveServerRedirectForProvisionalLoad();
2642 }
2643
2644 void FrameLoader::finishedLoadingDocument(DocumentLoader* loader)
2645 {
2646     m_client->finishedLoading(loader);
2647 }
2648
2649 bool FrameLoader::isReplacing() const
2650 {
2651     return m_loadType == FrameLoadTypeReplace;
2652 }
2653
2654 void FrameLoader::setReplacing()
2655 {
2656     m_loadType = FrameLoadTypeReplace;
2657 }
2658
2659 void FrameLoader::revertToProvisional(DocumentLoader* loader)
2660 {
2661     m_client->revertToProvisionalState(loader);
2662 }
2663
2664 bool FrameLoader::subframeIsLoading() const
2665 {
2666     // It's most likely that the last added frame is the last to load so we walk backwards.
2667     for (Frame* child = m_frame->tree()->lastChild(); child; child = child->tree()->previousSibling()) {
2668         FrameLoader* childLoader = child->loader();
2669         DocumentLoader* documentLoader = childLoader->documentLoader();
2670         if (documentLoader && documentLoader->isLoadingInAPISense())
2671             return true;
2672         documentLoader = childLoader->provisionalDocumentLoader();
2673         if (documentLoader && documentLoader->isLoadingInAPISense())
2674             return true;
2675     }
2676     return false;
2677 }
2678
2679 void FrameLoader::willChangeTitle(DocumentLoader* loader)
2680 {
2681     m_client->willChangeTitle(loader);
2682 }
2683
2684 FrameLoadType FrameLoader::loadType() const
2685 {
2686     return m_loadType;
2687 }
2688
2689 void FrameLoader::stopPolicyCheck()
2690 {
2691     m_client->cancelPolicyCheck();
2692     PolicyCheck check = m_policyCheck;
2693     m_policyCheck.clear();
2694     check.cancel();
2695 }
2696
2697 void FrameLoader::checkLoadCompleteForThisFrame()
2698 {
2699     ASSERT(m_client->hasWebView());
2700
2701     switch (m_state) {
2702         case FrameStateProvisional: {
2703             if (m_delegateIsHandlingProvisionalLoadError)
2704                 return;
2705
2706             RefPtr<DocumentLoader> pdl = m_provisionalDocumentLoader;
2707             if (!pdl)
2708                 return;
2709                 
2710             // If we've received any errors we may be stuck in the provisional state and actually complete.
2711             const ResourceError& error = pdl->mainDocumentError();
2712             if (error.isNull())
2713                 return;
2714
2715             // Check all children first.
2716             RefPtr<HistoryItem> item;
2717             if (isBackForwardLoadType(loadType()) && m_frame == m_frame->page()->mainFrame())
2718                 item = m_currentHistoryItem;
2719                 
2720             bool shouldReset = true;
2721             if (!pdl->isLoadingInAPISense()) {
2722                 m_delegateIsHandlingProvisionalLoadError = true;
2723                 m_client->dispatchDidFailProvisionalLoad(error);
2724                 m_delegateIsHandlingProvisionalLoadError = false;
2725
2726                 // FIXME: can stopping loading here possibly have any effect, if isLoading is false,
2727                 // which it must be to be in this branch of the if? And is it OK to just do a full-on
2728                 // stopAllLoaders instead of stopLoadingSubframes?
2729                 stopLoadingSubframes();
2730                 pdl->stopLoading();
2731
2732                 // Finish resetting the load state, but only if another load hasn't been started by the
2733                 // delegate callback.
2734                 if (pdl == m_provisionalDocumentLoader)
2735                     clearProvisionalLoad();
2736                 else {
2737                     KURL unreachableURL = m_provisionalDocumentLoader->unreachableURL();
2738                     if (!unreachableURL.isEmpty() && unreachableURL == pdl->request().url())
2739                         shouldReset = false;
2740                 }
2741             }
2742             if (shouldReset && item && m_frame->page())
2743                  m_frame->page()->backForwardList()->goToItem(item.get());
2744
2745             return;
2746         }
2747         
2748         case FrameStateCommittedPage: {
2749             DocumentLoader* dl = m_documentLoader.get();            
2750             if (!dl || dl->isLoadingInAPISense())
2751                 return;
2752
2753             markLoadComplete();
2754
2755             // FIXME: Is this subsequent work important if we already navigated away?
2756             // Maybe there are bugs because of that, or extra work we can skip because
2757             // the new page is ready.
2758
2759             m_client->forceLayoutForNonHTML();
2760              
2761             // If the user had a scroll point, scroll to it, overriding the anchor point if any.
2762             if ((isBackForwardLoadType(m_loadType) || m_loadType == FrameLoadTypeReload)
2763                     && m_frame->page() && m_frame->page()->backForwardList())
2764                 restoreScrollPositionAndViewState();
2765
2766             if (m_creatingInitialEmptyDocument)
2767                 return;
2768
2769             const ResourceError& error = dl->mainDocumentError();
2770             if (!error.isNull())
2771                 m_client->dispatchDidFailLoad(error);
2772             else
2773                 m_client->dispatchDidFinishLoad();
2774
2775             if (m_frame->page())
2776                 m_frame->page()->progress()->progressCompleted(m_frame);
2777             return;
2778         }
2779         
2780         case FrameStateComplete:
2781             // Even if already complete, we might have set a previous item on a frame that
2782             // didn't do any data loading on the past transaction. Make sure to clear these out.
2783             m_client->frameLoadCompleted();
2784             return;
2785     }
2786
2787     ASSERT_NOT_REACHED();
2788 }
2789
2790 void FrameLoader::continueAfterContentPolicy(PolicyAction policy)
2791 {
2792     PolicyCheck check = m_policyCheck;
2793     m_policyCheck.clear();
2794     check.call(policy);
2795 }
2796
2797 void FrameLoader::continueLoadAfterWillSubmitForm(PolicyAction)
2798 {
2799     if (!m_provisionalDocumentLoader)
2800         return;
2801
2802     m_provisionalDocumentLoader->prepareForLoadStart();
2803
2804     DocumentLoader* activeDocLoader = activeDocumentLoader();
2805     if (activeDocLoader && activeDocLoader->isLoadingMainResource())
2806         return;
2807
2808     m_provisionalDocumentLoader->setLoadingFromCachedPage(false);
2809
2810     unsigned long identifier = m_frame->page()->progress()->createUniqueIdentifier();
2811     m_client->assignIdentifierToInitialRequest(identifier, m_provisionalDocumentLoader.get(), m_provisionalDocumentLoader->originalRequest());
2812
2813     if (!m_provisionalDocumentLoader->startLoadingMainResource(identifier))
2814         m_provisionalDocumentLoader->updateLoading();
2815 }
2816
2817 void FrameLoader::didFirstLayout()
2818 {
2819     if (isBackForwardLoadType(m_loadType) && m_frame->page() && m_frame->page()->backForwardList())
2820         restoreScrollPositionAndViewState();
2821
2822     m_firstLayoutDone = true;
2823     m_client->dispatchDidFirstLayout();
2824 }
2825
2826 void FrameLoader::frameLoadCompleted()
2827 {
2828     m_client->frameLoadCompleted();
2829
2830     // After a canceled provisional load, firstLayoutDone is false.
2831     // Reset it to true if we're displaying a page.
2832     if (m_documentLoader)
2833         m_firstLayoutDone = true;
2834 }
2835
2836 bool FrameLoader::firstLayoutDone() const
2837 {
2838     return m_firstLayoutDone;
2839 }
2840
2841 bool FrameLoader::isQuickRedirectComing() const
2842 {
2843     return m_quickRedirectComing;
2844 }
2845
2846 void FrameLoader::detachChildren()
2847 {
2848     // FIXME: Is it really necessary to do this in reverse order?
2849     Frame* previous;
2850     for (Frame* child = m_frame->tree()->lastChild(); child; child = previous) {
2851         previous = child->tree()->previousSibling();
2852         child->loader()->detachFromParent();
2853     }
2854 }
2855
2856 void FrameLoader::recursiveCheckLoadComplete()
2857 {
2858     Vector<RefPtr<Frame>, 10> frames;
2859     
2860     for (RefPtr<Frame> frame = m_frame->tree()->firstChild(); frame; frame = frame->tree()->nextSibling())
2861         frames.append(frame);
2862     
2863     unsigned size = frames.size();
2864     for (unsigned i = 0; i < size; i++)
2865         frames[i]->loader()->recursiveCheckLoadComplete();
2866     
2867     checkLoadCompleteForThisFrame();
2868 }
2869
2870 // Called every time a resource is completely loaded, or an error is received.
2871 void FrameLoader::checkLoadComplete()
2872 {
2873     ASSERT(m_client->hasWebView());
2874     
2875     // FIXME: Always traversing the entire frame tree is a bit inefficient, but 
2876     // is currently needed in order to null out the previous history item for all frames.
2877     if (Page* page = m_frame->page())
2878         page->mainFrame()->loader()->recursiveCheckLoadComplete();
2879 }
2880
2881 int FrameLoader::numPendingOrLoadingRequests(bool recurse) const
2882 {
2883     if (!recurse)
2884         return numRequests(m_frame->document());
2885
2886     int count = 0;
2887     for (Frame* frame = m_frame; frame; frame = frame->tree()->traverseNext(m_frame))
2888         count += numRequests(frame->document());
2889     return count;
2890 }
2891
2892 FrameLoaderClient* FrameLoader::client() const
2893 {
2894     return m_client;
2895 }
2896
2897 void FrameLoader::submitForm(const FrameLoadRequest& request, Event* event)
2898 {
2899     // FIXME: We'd like to remove this altogether and fix the multiple form submission issue another way.
2900     // We do not want to submit more than one form from the same page,
2901     // nor do we want to submit a single form more than once.
2902     // This flag prevents these from happening; not sure how other browsers prevent this.
2903     // The flag is reset in each time we start handle a new mouse or key down event, and
2904     // also in setView since this part may get reused for a page from the back/forward cache.
2905     // The form multi-submit logic here is only needed when we are submitting a form that affects this frame.
2906     // FIXME: Frame targeting is only one of the ways the submission could end up doing something other
2907     // than replacing this frame's content, so this check is flawed. On the other hand, the check is hardly
2908     // needed any more now that we reset m_submittedFormURL on each mouse or key down event.
2909     Frame* target = m_frame->tree()->find(request.frameName());
2910     if (m_frame->tree()->isDescendantOf(target)) {
2911         if (m_submittedFormURL == request.resourceRequest().url())
2912             return;
2913         m_submittedFormURL = request.resourceRequest().url();
2914     }
2915
2916     // FIXME: Why do we always pass true for userGesture?
2917     load(request, true, event, m_formAboutToBeSubmitted.get(), m_formValuesAboutToBeSubmitted);
2918
2919     clearRecordedFormValues();
2920 }
2921
2922 void FrameLoader::urlSelected(const FrameLoadRequest& request, Event* event, bool userGesture)
2923 {
2924     FrameLoadRequest copy = request;
2925     if (copy.resourceRequest().httpReferrer().isEmpty())
2926         copy.resourceRequest().setHTTPReferrer(m_outgoingReferrer);
2927
2928     load(copy, userGesture, event, 0, HashMap<String, String>());
2929 }
2930     
2931 String FrameLoader::userAgent(const KURL& url) const
2932 {
2933     return m_client->userAgent(url);
2934 }
2935
2936 void FrameLoader::tokenizerProcessedData()
2937 {
2938     ASSERT(m_frame->page());
2939     ASSERT(m_frame->document());
2940
2941     checkCompleted();
2942 }
2943
2944 void FrameLoader::didTellBridgeAboutLoad(const String& URL)
2945 {
2946     m_urlsBridgeKnowsAbout.add(URL);
2947 }
2948
2949 bool FrameLoader::haveToldBridgeAboutLoad(const String& URL)
2950 {
2951     return m_urlsBridgeKnowsAbout.contains(URL);
2952 }
2953
2954 void FrameLoader::handledOnloadEvents()
2955 {
2956     m_client->dispatchDidHandleOnloadEvents();
2957 }
2958
2959 void FrameLoader::frameDetached()
2960 {
2961     stopAllLoaders();
2962     detachFromParent();
2963 }
2964
2965 void FrameLoader::detachFromParent()
2966 {
2967     RefPtr<Frame> protect(m_frame);
2968
2969     closeURL();
2970     stopAllLoaders();
2971     saveScrollPositionAndViewStateToItem(currentHistoryItem());
2972     detachChildren();
2973     m_client->detachedFromParent2();
2974     setDocumentLoader(0);
2975     m_client->detachedFromParent3();
2976     if (Frame* parent = m_frame->tree()->parent()) {
2977         parent->tree()->removeChild(m_frame);
2978         parent->loader()->scheduleCheckCompleted();
2979     } else {
2980         m_frame->setView(0);
2981         m_frame->pageDestroyed();
2982     }
2983 #if PLATFORM(MAC)
2984     [m_frame->bridge() close];
2985 #endif
2986     m_client->detachedFromParent4();
2987 }
2988
2989 void FrameLoader::dispatchDidChangeLocationWithinPage()
2990 {
2991     m_client->dispatchDidChangeLocationWithinPage();
2992 }
2993
2994 void FrameLoader::dispatchDidFinishLoadToClient()
2995 {
2996     m_client->didFinishLoad();
2997 }
2998
2999 void FrameLoader::updateGlobalHistoryForStandardLoad(const KURL& url)
3000 {
3001     m_client->updateGlobalHistoryForStandardLoad(url);
3002 }
3003
3004 void FrameLoader::updateGlobalHistoryForReload(const KURL& url)
3005 {
3006     m_client->updateGlobalHistoryForReload(url);
3007 }
3008
3009 bool FrameLoader::shouldGoToHistoryItem(HistoryItem* item) const
3010 {
3011     return m_client->shouldGoToHistoryItem(item);
3012 }
3013
3014 void FrameLoader::addExtraFieldsToRequest(ResourceRequest& request, bool mainResource, bool alwaysFromRequest)
3015 {
3016     applyUserAgent(request);
3017     
3018     if (m_loadType == FrameLoadTypeReload)
3019         request.setHTTPHeaderField("Cache-Control", "max-age=0");
3020     
3021     // Don't set the cookie policy URL if it's already been set.
3022     if (request.mainDocumentURL().isEmpty()) {
3023         if (mainResource && (isLoadingMainFrame() || alwaysFromRequest))
3024             request.setMainDocumentURL(request.url());
3025         else
3026             request.setMainDocumentURL(m_frame->page()->mainFrame()->loader()->url());
3027     }
3028     
3029     if (mainResource)
3030         request.setHTTPAccept("text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5");
3031 }
3032
3033 void FrameLoader::committedLoad(DocumentLoader* loader, const char* data, int length)
3034 {
3035     m_client->committedLoad(loader, data, length);
3036 }
3037
3038 void FrameLoader::post(const KURL& URL, const String& referrer, const String& frameName, PassRefPtr<FormData> formData, 
3039     const String& contentType, Event* event, HTMLFormElement* form, const HashMap<String, String>& formValues)
3040 {
3041     // When posting, use the NSURLRequestReloadIgnoringCacheData load flag.
3042     // This prevents a potential bug which may cause a page with a form that uses itself
3043     // as an action to be returned from the cache without submitting.
3044
3045     // FIXME: Where's the code that implements what the comment above says?
3046
3047     ResourceRequest request(URL);
3048     addExtraFieldsToRequest(request, true, true);
3049
3050     if (!referrer.isEmpty())
3051         request.setHTTPReferrer(referrer);
3052     request.setHTTPMethod("POST");
3053     request.setHTTPBody(formData);
3054     request.setHTTPContentType(contentType);
3055
3056     NavigationAction action(URL, FrameLoadTypeStandard, true, event);
3057
3058     RefPtr<FormState> formState;
3059     if (form && !formValues.isEmpty())
3060         formState = FormState::create(form, formValues, m_frame);
3061
3062     if (!frameName.isEmpty()) {
3063         if (Frame* targetFrame = m_frame->tree()->find(frameName))
3064             targetFrame->loader()->load(request, action, FrameLoadTypeStandard, formState.release());
3065         else
3066             checkNewWindowPolicy(action, request, formState.release(), frameName);
3067     } else
3068         load(request, action, FrameLoadTypeStandard, formState.release());
3069 }
3070
3071 bool FrameLoader::isReloading() const
3072 {
3073     return documentLoader()->request().cachePolicy() == ReloadIgnoringCacheData;
3074 }
3075
3076 void FrameLoader::loadEmptyDocumentSynchronously()
3077 {
3078     ResourceRequest request(KURL(""));
3079     load(request);
3080 }
3081
3082 void FrameLoader::loadResourceSynchronously(const ResourceRequest& request, ResourceError& error, ResourceResponse& response, Vector<char>& data)
3083 {
3084     // Since this is a subresource, we can load any URL (we ignore the return value).
3085     // But we still want to know whether we should hide the referrer or not, so we call the canLoad method.
3086     String referrer = m_outgoingReferrer;
3087     if (shouldHideReferrer(request.url(), referrer))
3088         referrer = String();
3089     
3090     ResourceRequest initialRequest = request;
3091     initialRequest.setTimeoutInterval(10);
3092     
3093     if (initialRequest.isConditional())
3094         initialRequest.setCachePolicy(ReloadIgnoringCacheData);
3095     else
3096         initialRequest.setCachePolicy(documentLoader()->request().cachePolicy());
3097     
3098     if (!referrer.isEmpty())
3099         initialRequest.setHTTPReferrer(referrer);
3100     
3101     initialRequest.setMainDocumentURL(m_frame->page()->mainFrame()->loader()->documentLoader()->request().url());
3102     initialRequest.setHTTPUserAgent(client()->userAgent(request.url()));
3103     
3104     unsigned long identifier = 0;    
3105     ResourceRequest newRequest(initialRequest);
3106     requestFromDelegate(newRequest, identifier, error);
3107
3108     if (error.isNull()) {
3109         ASSERT(!newRequest.isNull());
3110         didTellBridgeAboutLoad(newRequest.url().url());
3111         ResourceHandle::loadResourceSynchronously(newRequest, error, response, data);
3112     }
3113     
3114     sendRemainingDelegateMessages(identifier, response, data.size(), error);
3115 }
3116
3117 void FrameLoader::assignIdentifierToInitialRequest(unsigned long identifier, const ResourceRequest& clientRequest)
3118 {
3119     return m_client->assignIdentifierToInitialRequest(identifier, activeDocumentLoader(), clientRequest);
3120 }
3121
3122 void FrameLoader::willSendRequest(ResourceLoader* loader, ResourceRequest& clientRequest, const ResourceResponse& redirectResponse)
3123 {
3124     applyUserAgent(clientRequest);
3125     m_client->dispatchWillSendRequest(loader->documentLoader(), loader->identifier(), clientRequest, redirectResponse);
3126 }
3127
3128 void FrameLoader::didReceiveResponse(ResourceLoader* loader, const ResourceResponse& r)
3129 {
3130     activeDocumentLoader()->addResponse(r);
3131     
3132     if (m_frame->page())
3133         m_frame->page()->progress()->incrementProgress(loader->identifier(), r);
3134     m_client->dispatchDidReceiveResponse(loader->documentLoader(), loader->identifier(), r);
3135 }
3136
3137 void FrameLoader::didReceiveData(ResourceLoader* loader, const char* data, int length, int lengthReceived)
3138 {
3139     if (m_frame->page())
3140         m_frame->page()->progress()->incrementProgress(loader->identifier(), data, length);
3141     m_client->dispatchDidReceiveContentLength(loader->documentLoader(), loader->identifier(), lengthReceived);
3142 }
3143
3144 void FrameLoader::didFailToLoad(ResourceLoader* loader, const ResourceError& error)
3145 {
3146     if (m_frame->page())
3147         m_frame->page()->progress()->completeProgress(loader->identifier());
3148     if (!error.isNull())
3149         m_client->dispatchDidFailLoading(loader->documentLoader(), loader->identifier(), error);
3150 }
3151
3152 const ResourceRequest& FrameLoader::originalRequest() const
3153 {
3154     return activeDocumentLoader()->originalRequestCopy();
3155 }
3156
3157 void FrameLoader::receivedMainResourceError(const ResourceError& error, bool isComplete)
3158 {
3159     // Retain because the stop may release the last reference to it.
3160     RefPtr<Frame> protect(m_frame);
3161
3162     RefPtr<DocumentLoader> loader = activeDocumentLoader();
3163     
3164     if (isComplete) {
3165         // FIXME: Don't want to do this if an entirely new load is going, so should check
3166         // that both data sources on the frame are either this or nil.
3167         stop();
3168         if (m_client->shouldFallBack(error))
3169             handleFallbackContent();
3170     }
3171     
3172     if (m_state == FrameStateProvisional) {
3173         KURL failedURL = m_provisionalDocumentLoader->originalRequestCopy().url();
3174         didNotOpenURL(failedURL);
3175             
3176         // We might have made a page cache item, but now we're bailing out due to an error before we ever
3177         // transitioned to the new page (before WebFrameState == commit).  The goal here is to restore any state
3178         // so that the existing view (that wenever got far enough to replace) can continue being used.
3179         m_frame->document()->setInPageCache(false);
3180         invalidateCurrentItemCachedPage();
3181         
3182         // Call clientRedirectCancelledOrFinished here so that the frame load delegate is notified that the redirect's
3183         // status has changed, if there was a redirect. The frame load delegate may have saved some state about
3184         // the redirect in its -webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:. Since we are definitely
3185         // not going to use this provisional resource, as it was cancelled, notify the frame load delegate that the redirect
3186         // has ended.
3187         if (m_sentRedirectNotification)
3188             clientRedirectCancelledOrFinished(false);
3189     }
3190     
3191     
3192     loader->mainReceivedError(error, isComplete);
3193 }
3194
3195 void FrameLoader::callContinueFragmentScrollAfterNavigationPolicy(void* argument,
3196     const ResourceRequest& request, PassRefPtr<FormState>, bool shouldContinue)
3197 {
3198     FrameLoader* loader = static_cast<FrameLoader*>(argument);
3199     loader->continueFragmentScrollAfterNavigationPolicy(request, shouldContinue);
3200 }
3201
3202 void FrameLoader::continueFragmentScrollAfterNavigationPolicy(const ResourceRequest& request, bool shouldContinue)
3203 {
3204     bool isRedirect = m_quickRedirectComing;
3205     m_quickRedirectComing = false;
3206
3207     if (!shouldContinue)
3208         return;
3209
3210     KURL URL = request.url();
3211     
3212     m_documentLoader->replaceRequestURLForAnchorScroll(URL);
3213     if (!isRedirect && !shouldTreatURLAsSameAsCurrent(URL)) {
3214         // NB: must happen after _setURL, since we add based on the current request.
3215         // Must also happen before we openURL and displace the scroll position, since
3216         // adding the BF item will save away scroll state.
3217         
3218         // NB2:  If we were loading a long, slow doc, and the user anchor nav'ed before
3219         // it was done, currItem is now set the that slow doc, and prevItem is whatever was
3220         // before it.  Adding the b/f item will bump the slow doc down to prevItem, even
3221         // though its load is not yet done.  I think this all works out OK, for one because
3222         // we have already saved away the scroll and doc state for the long slow load,
3223         // but it's not an obvious case.
3224
3225         addHistoryItemForFragmentScroll();
3226     }
3227     
3228     scrollToAnchor(URL);
3229     
3230     if (!isRedirect)
3231         // This will clear previousItem from the rest of the frame tree that didn't
3232         // doing any loading. We need to make a pass on this now, since for anchor nav
3233         // we'll not go through a real load and reach Completed state.
3234         checkLoadComplete();
3235  
3236     dispatchDidChangeLocationWithinPage();
3237     m_client->didFinishLoad();
3238 }
3239
3240 void FrameLoader::opened()
3241 {
3242     if (m_loadType == FrameLoadTypeStandard && m_documentLoader->isClientRedirect())
3243         updateHistoryForClientRedirect();
3244
3245     if (m_documentLoader->isLoadingFromCachedPage()) {
3246         m_frame->document()->didRestoreFromCache();
3247         
3248         // Force a layout to update view size and thereby update scrollbars.
3249         m_client->forceLayout();
3250
3251         const ResponseVector& responses = m_documentLoader->responses();
3252         size_t count = responses.size();
3253         for (size_t i = 0; i < count; i++) {
3254             const ResourceResponse& response = responses[i];
3255             // FIXME: If the WebKit client changes or cancels the request, this is not respected.
3256             ResourceError error;
3257             unsigned long identifier;
3258             ResourceRequest request(response.url());
3259             requestFromDelegate(request, identifier, error);
3260             sendRemainingDelegateMessages(identifier, response, response.expectedContentLength(), error);
3261         }
3262         
3263         m_client->loadedFromCachedPage();
3264
3265         m_documentLoader->setPrimaryLoadComplete(true);
3266
3267         // FIXME: Why only this frame and not parent frames?
3268         checkLoadCompleteForThisFrame();
3269     }
3270 }
3271
3272 void FrameLoader::checkNewWindowPolicy(const NavigationAction& action, const ResourceRequest& request,
3273     PassRefPtr<FormState> formState, const String& frameName)
3274 {
3275     m_policyCheck.set(request, formState, frameName,
3276         callContinueLoadAfterNewWindowPolicy, this);
3277     m_client->dispatchDecidePolicyForNewWindowAction(&FrameLoader::continueAfterNewWindowPolicy,
3278         action, request, frameName);
3279 }
3280
3281 void FrameLoader::continueAfterNewWindowPolicy(PolicyAction policy)
3282 {
3283     PolicyCheck check = m_policyCheck;
3284     m_policyCheck.clear();
3285
3286     switch (policy) {
3287         case PolicyIgnore:
3288             check.clearRequest();
3289             break;
3290         case PolicyDownload:
3291             m_client->startDownload(check.request());
3292             check.clearRequest();
3293             break;
3294         case PolicyUse:
3295             break;
3296     }
3297
3298     check.call(policy == PolicyUse);
3299 }
3300
3301 void FrameLoader::checkNavigationPolicy(const ResourceRequest& request, DocumentLoader* loader,
3302     PassRefPtr<FormState> formState, NavigationPolicyDecisionFunction function, void* argument)
3303 {
3304     NavigationAction action = loader->triggeringAction();
3305     if (action.isEmpty()) {
3306         action = NavigationAction(request.url(), NavigationTypeOther);
3307         loader->setTriggeringAction(action);
3308     }
3309         
3310     // Don't ask more than once for the same request or if we are loading an empty URL.
3311     // This avoids confusion on the part of the client.
3312     if (request == loader->lastCheckedRequest() || request.url().isEmpty()) {
3313         function(argument, request, 0, true);
3314         return;
3315     }
3316     
3317     // We are always willing to show alternate content for unreachable URLs;
3318     // treat it like a reload so it maintains the right state for b/f list.
3319     if (loader->substituteData().isValid() && !loader->substituteData().failingURL().isEmpty()) {
3320         if (isBackForwardLoadType(m_policyLoadType))
3321             m_policyLoadType = FrameLoadTypeReload;
3322         function(argument, request, 0, true);
3323         return;
3324     }
3325     
3326     loader->setLastCheckedRequest(request);
3327
3328     m_policyCheck.set(request, formState, function, argument);
3329
3330     m_delegateIsDecidingNavigationPolicy = true;
3331     m_client->dispatchDecidePolicyForNavigationAction(&FrameLoader::continueAfterNavigationPolicy,
3332         action, request);
3333     m_delegateIsDecidingNavigationPolicy = false;
3334 }
3335
3336 void FrameLoader::continueAfterNavigationPolicy(PolicyAction policy)
3337 {
3338     PolicyCheck check = m_policyCheck;
3339     m_policyCheck.clear();
3340
3341     switch (policy) {
3342         case PolicyIgnore:
3343             check.clearRequest();
3344             break;
3345         case PolicyDownload:
3346             m_client->startDownload(check.request());
3347             check.clearRequest();
3348             break;
3349         case PolicyUse: {
3350             ResourceRequest request(check.request());
3351             
3352             if (!m_client->canHandleRequest(request)) {
3353                 handleUnimplementablePolicy(m_client->cannotShowURLError(check.request()));
3354                 check.clearRequest();
3355             }
3356             break;
3357         }
3358     }
3359
3360     check.call(policy == PolicyUse);
3361 }
3362
3363 void FrameLoader::callContinueLoadAfterNavigationPolicy(void* argument,
3364     const ResourceRequest& request, PassRefPtr<FormState> formState, bool shouldContinue)
3365 {
3366     FrameLoader* loader = static_cast<FrameLoader*>(argument);
3367     loader->continueLoadAfterNavigationPolicy(request, formState, shouldContinue);
3368 }
3369
3370 void FrameLoader::continueLoadAfterNavigationPolicy(const ResourceRequest& request, PassRefPtr<FormState> formState, bool shouldContinue)
3371 {
3372     // If we loaded an alternate page to replace an unreachableURL, we'll get in here with a
3373     // nil policyDataSource because loading the alternate page will have passed
3374     // through this method already, nested; otherwise, policyDataSource should still be set.
3375     ASSERT(m_policyDocumentLoader || !m_provisionalDocumentLoader->unreachableURL().isEmpty());
3376
3377     bool isTargetItem = m_provisionalHistoryItem ? m_provisionalHistoryItem->isTargetItem() : false;
3378
3379     // Two reasons we can't continue:
3380     //    1) Navigation policy delegate said we can't so request is nil. A primary case of this 
3381     //       is the user responding Cancel to the form repost nag sheet.
3382     //    2) User responded Cancel to an alert popped up by the before unload event handler.
3383     // The "before unload" event handler runs only for the main frame.
3384     bool canContinue = shouldContinue && (!isLoadingMainFrame() || m_frame->shouldClose());
3385
3386     if (!canContinue) {
3387         // If we were waiting for a quick redirect, but the policy delegate decided to ignore it, then we 
3388         // need to report that the client redirect was cancelled.
3389         if (m_quickRedirectComing)
3390             clientRedirectCancelledOrFinished(false);
3391
3392         setPolicyDocumentLoader(0);
3393
3394         // If the navigation request came from the back/forward menu, and we punt on it, we have the 
3395         // problem that we have optimistically moved the b/f cursor already, so move it back.  For sanity, 
3396         // we only do this when punting a navigation for the target frame or top-level frame.  
3397         if ((isTargetItem || isLoadingMainFrame()) && isBackForwardLoadType(m_policyLoadType) && m_frame->page()) {
3398             Frame* mainFrame = m_frame->page()->mainFrame();
3399             if (HistoryItem* resetItem = mainFrame->loader()->m_currentHistoryItem.get())
3400                 m_frame->page()->backForwardList()->goToItem(resetItem);
3401         }
3402         return;
3403     }
3404
3405     FrameLoadType type = m_policyLoadType;
3406     stopAllLoaders();
3407     setProvisionalDocumentLoader(m_policyDocumentLoader.get());
3408     m_loadType = type;
3409     setState(FrameStateProvisional);
3410
3411     setPolicyDocumentLoader(0);
3412
3413     if (isBackForwardLoadType(type) && loadProvisionalItemFromCachedPage())
3414         return;
3415
3416     if (formState)
3417         m_client->dispatchWillSubmitForm(&FrameLoader::continueLoadAfterWillSubmitForm, formState);
3418     else
3419         continueLoadAfterWillSubmitForm();
3420 }
3421
3422
3423 void FrameLoader::callContinueLoadAfterNewWindowPolicy(void* argument,
3424     const ResourceRequest& request, PassRefPtr<FormState> formState, const String& frameName, bool shouldContinue)
3425 {
3426     FrameLoader* loader = static_cast<FrameLoader*>(argument);
3427     loader->continueLoadAfterNewWindowPolicy(request, formState, frameName, shouldContinue);
3428 }
3429
3430 void FrameLoader::continueLoadAfterNewWindowPolicy(const ResourceRequest& request,
3431     PassRefPtr<FormState> formState, const String& frameName, bool shouldContinue)
3432 {
3433     if (!shouldContinue)
3434         return;
3435
3436     RefPtr<Frame> frame = m_frame;
3437     RefPtr<Frame> mainFrame = m_client->dispatchCreatePage();
3438     if (!mainFrame)
3439         return;
3440
3441     if (frameName != "_blank")
3442         mainFrame->tree()->setName(frameName);
3443     mainFrame->loader()->m_client->dispatchShow();
3444     mainFrame->loader()->setOpener(frame.get());
3445     mainFrame->loader()->load(request, NavigationAction(), FrameLoadTypeStandard, formState);
3446 }
3447
3448 void FrameLoader::sendRemainingDelegateMessages(unsigned long identifier, const ResourceResponse& response, unsigned length, const ResourceError& error)
3449 {    
3450     if (!response.isNull())
3451         m_client->dispatchDidReceiveResponse(m_documentLoader.get(), identifier, response);
3452     
3453     if (length > 0)
3454         m_client->dispatchDidReceiveContentLength(m_documentLoader.get(), identifier, length);
3455     
3456     if (error.isNull())
3457         m_client->dispatchDidFinishLoading(m_documentLoader.get(), identifier);
3458     else
3459         m_client->dispatchDidFailLoading(m_documentLoader.get(), identifier, error);
3460 }
3461
3462 void FrameLoader::requestFromDelegate(ResourceRequest& request, unsigned long& identifier, ResourceError& error)
3463 {
3464     ASSERT(!request.isNull());
3465
3466     identifier = m_frame->page()->progress()->createUniqueIdentifier();
3467     m_client->assignIdentifierToInitialRequest(identifier, m_documentLoader.get(), request);
3468
3469     ResourceRequest newRequest(request);
3470     m_client->dispatchWillSendRequest(m_documentLoader.get(), identifier, newRequest, ResourceResponse());
3471
3472     if (newRequest.isNull())
3473         error = m_client->cancelledError(request);
3474     else
3475         error = ResourceError();
3476
3477     request = newRequest;
3478 }
3479
3480 void FrameLoader::loadedResourceFromMemoryCache(const ResourceRequest& request, const ResourceResponse& response, int length)
3481 {
3482     if (m_client->dispatchDidLoadResourceFromMemoryCache(m_documentLoader.get(), request, response, length))
3483         return;
3484
3485     unsigned long identifier;
3486     ResourceError error;
3487     ResourceRequest r(request);
3488     requestFromDelegate(r, identifier, error);
3489     sendRemainingDelegateMessages(identifier, response, length, error);
3490 }
3491
3492 void FrameLoader::applyUserAgent(ResourceRequest& request)
3493 {
3494     String userAgent = client()->userAgent(request.url());
3495     ASSERT(!userAgent.isNull());
3496     request.setHTTPUserAgent(userAgent);
3497 }
3498
3499 bool FrameLoader::canGoBackOrForward(int distance) const
3500 {
3501     if (distance == 0)
3502         return true;
3503     if (distance > 0 && distance <= m_frame->page()->backForwardList()->forwardListCount())
3504         return true;
3505     if (distance < 0 && -distance <= m_frame->page()->backForwardList()->backListCount())
3506         return true;
3507     return false;
3508 }
3509
3510 int FrameLoader::getHistoryLength()
3511 {
3512     return m_frame->page()->backForwardList()->backListCount() + 1;
3513 }
3514
3515 KURL FrameLoader::historyURL(int distance)
3516 {
3517     BackForwardList *list = m_frame->page()->backForwardList();
3518     HistoryItem* item = list->itemAtIndex(distance);
3519     if (!item) {
3520         if (distance > 0) {
3521             int forwardListCount = list->forwardListCount();
3522             if (forwardListCount > 0)
3523                 item = list->itemAtIndex(forwardListCount);
3524         } else {
3525             int backListCount = list->backListCount();
3526             if (backListCount > 0)
3527                 item = list->itemAtIndex(-backListCount);
3528         }
3529     }
3530     if (item)
3531         return item->url();
3532
3533     return KURL();
3534 }
3535
3536 void FrameLoader::addHistoryItemForFragmentScroll()
3537 {
3538     addBackForwardItemClippedAtTarget(false);
3539 }
3540
3541 bool FrameLoader::loadProvisionalItemFromCachedPage()
3542 {
3543     if (!m_provisionalHistoryItem || !m_provisionalHistoryItem->cachedPage())
3544         return false;
3545
3546     if (!m_provisionalHistoryItem->cachedPage()->document())
3547         return false;
3548     
3549     provisionalDocumentLoader()->loadFromCachedPage(m_provisionalHistoryItem->cachedPage());
3550     return true;
3551 }
3552
3553 void FrameLoader::cachePageToHistoryItem(HistoryItem* item)
3554 {
3555     RefPtr<CachedPage> cachedPage = CachedPage::create(m_frame->page());
3556     cachedPage->setTimeStampToNow();
3557     cachedPage->setDocumentLoader(documentLoader());
3558     m_client->saveDocumentViewToCachedPage(cachedPage.get());
3559
3560     item->setCachedPage(cachedPage);
3561
3562     LOG(PageCache, "WebCorePageCache: CachedPage %p created for HistoryItem %p (%s)", 
3563         m_currentHistoryItem->cachedPage(), m_currentHistoryItem.get(), 
3564         m_currentHistoryItem->urlString().ascii().data());
3565 }
3566
3567 bool FrameLoader::shouldTreatURLAsSameAsCurrent(const KURL& URL) const
3568 {
3569     if (!m_currentHistoryItem)
3570         return false;
3571     return URL == m_currentHistoryItem->url() || URL == m_currentHistoryItem->originalURL();
3572 }
3573
3574 PassRefPtr<HistoryItem> FrameLoader::createHistoryItem(bool useOriginal)
3575 {
3576     DocumentLoader* docLoader = documentLoader();
3577     
3578     KURL unreachableURL = docLoader ? docLoader->unreachableURL() : KURL();
3579     
3580     KURL url;
3581     KURL originalURL;
3582
3583     if (!unreachableURL.isEmpty()) {
3584         url = unreachableURL;
3585         originalURL = unreachableURL;
3586     } else {
3587         originalURL = docLoader ? docLoader->originalURL() : KURL();
3588         if (useOriginal)
3589             url = originalURL;
3590         else if (docLoader)
3591             url = docLoader->requestURL();                
3592     }
3593
3594     LOG(History, "WebCoreHistory: Creating item for %s", url.url().ascii());
3595     
3596     // Frames that have never successfully loaded any content
3597     // may have no URL at all. Currently our history code can't
3598     // deal with such things, so we nip that in the bud here.
3599     // Later we may want to learn to live with nil for URL.
3600     // See bug 3368236 and related bugs for more information.
3601     if (url.isEmpty()) 
3602         url = KURL("about:blank");
3603     if (originalURL.isEmpty())
3604         originalURL = KURL("about:blank");
3605     
3606     RefPtr<HistoryItem> item = new HistoryItem(url, m_frame->tree()->name(), m_frame->tree()->parent() ? m_frame->tree()->parent()->tree()->name() : "", docLoader ? docLoader->title() : "");
3607     item->setOriginalURLString(originalURL.url());
3608     
3609     // Save form state if this is a POST
3610     if (docLoader) {
3611         if (useOriginal)
3612             item->setFormInfoFromRequest(docLoader->originalRequest());
3613         else
3614             item->setFormInfoFromRequest(docLoader->request());
3615     }
3616     
3617     // Set the item for which we will save document state
3618     m_previousHistoryItem = m_currentHistoryItem;
3619     m_currentHistoryItem = item;
3620     
3621     return item.release();
3622 }
3623
3624 void FrameLoader::addBackForwardItemClippedAtTarget(bool doClip)
3625 {
3626     if (!documentLoader()->urlForHistory().isEmpty()) {
3627         Frame* mainFrame = m_frame->page()->mainFrame();
3628         ASSERT(mainFrame);
3629         RefPtr<HistoryItem> item = mainFrame->loader()->createHistoryItemTree(m_frame, doClip);
3630         LOG(BackForward, "WebCoreBackForward - Adding backforward item %p for frame %s", item.get(), documentLoader()->URL().url().ascii());
3631         ASSERT(m_frame->page());
3632         m_frame->page()->backForwardList()->addItem(item);
3633     }
3634 }
3635
3636 PassRefPtr<HistoryItem> FrameLoader::createHistoryItemTree(Frame* targetFrame, bool clipAtTarget)
3637 {
3638     RefPtr<HistoryItem> bfItem = createHistoryItem(m_frame->tree()->parent() ? true : false);
3639     if (m_previousHistoryItem)
3640         saveScrollPositionAndViewStateToItem(m_previousHistoryItem.get());
3641     if (!(clipAtTarget && m_frame == targetFrame)) {
3642         // save frame state for items that aren't loading (khtml doesn't save those)
3643         saveDocumentState();
3644         for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
3645             bfItem->addChildItem(child->loader()->createHistoryItemTree(targetFrame, clipAtTarget));
3646     }
3647     if (m_frame == targetFrame)
3648         bfItem->setIsTargetItem(true);
3649     return bfItem;
3650 }
3651
3652 void FrameLoader::saveScrollPositionAndViewStateToItem(HistoryItem* item)
3653 {
3654     if (!item || !m_frame->view())
3655         return;
3656         
3657     item->setScrollPoint(IntPoint(m_frame->view()->contentsX(), m_frame->view()->contentsY()));
3658     // FIXME: It would be great to work out a way to put this code in WebCore instead of calling through to the client.
3659     m_client->saveViewStateToItem(item);
3660 }
3661
3662 /*
3663  There is a race condition between the layout and load completion that affects restoring the scroll position.
3664  We try to restore the scroll position at both the first layout and upon load completion.
3665  
3666  1) If first layout happens before the load completes, we want to restore the scroll position then so that the
3667  first time we draw the page is already scrolled to the right place, instead of starting at the top and later
3668  jumping down.  It is possible that the old scroll position is past the part of the doc laid out so far, in
3669  which case the restore silent fails and we will fix it in when we try to restore on doc completion.
3670  2) If the layout happens after the load completes, the attempt to restore at load completion time silently
3671  fails.  We then successfully restore it when the layout happens.
3672 */
3673 void FrameLoader::restoreScrollPositionAndViewState()
3674 {
3675     if (!m_committedFirstRealDocumentLoad)
3676         return;
3677
3678     ASSERT(m_currentHistoryItem);
3679     
3680     // FIXME: As the ASSERT attests, it seems we should always have a currentItem here.
3681     // One counterexample is <rdar://problem/4917290>
3682     // For now, to cover this issue in release builds, there is no technical harm to returning
3683     // early and from a user standpoint - as in the above radar - the previous page load failed 
3684     // so there *is* no scroll or view state to restore!
3685     if (!m_currentHistoryItem)
3686         return;
3687     
3688     // FIXME: It would be great to work out a way to put this code in WebCore instead of calling
3689     // through to the client. It's currently used only for the PDF view on Mac.
3690     m_client->restoreViewState();
3691     
3692     if (FrameView* view = m_frame->view())
3693         if (!view->wasScrolledByUser()) {
3694             const IntPoint& scrollPoint = m_currentHistoryItem->scrollPoint();
3695             view->setContentsPos(scrollPoint.x(), scrollPoint.y());
3696         }
3697 }
3698
3699 void FrameLoader::purgePageCache()
3700 {
3701     if (!m_frame->page())
3702         return;
3703         
3704     BackForwardList* bfList = m_frame->page()->backForwardList();
3705     unsigned sizeLimit = bfList->pageCacheSize();
3706     unsigned pagesCached = 0;
3707
3708     HistoryItemVector items;
3709     bfList->backListWithLimit(INT_MAX, items);
3710     RefPtr<HistoryItem> oldestItem;
3711     
3712     unsigned int i = 0;
3713     
3714     for (; i < items.size(); ++i) {
3715         if (items[i]->cachedPage()) {
3716             if (!oldestItem)
3717                 oldestItem = items[i];
3718             pagesCached++;
3719         }
3720     }
3721     
3722     // Snapback items are never directly purged here.
3723     if (pagesCached >= sizeLimit && oldestItem) {
3724         LOG(PageCache, "Purging back/forward cache, %s\n", oldestItem->url().url().ascii());
3725         oldestItem->setCachedPage(0);
3726     }
3727 }
3728
3729 void FrameLoader::invalidateCurrentItemCachedPage()
3730 {
3731     // When we are pre-commit, the currentItem is where the pageCache data resides    
3732     CachedPage* cachedPage = m_currentHistoryItem ? m_currentHistoryItem->cachedPage() : 0;
3733
3734     // FIXME: This is a grotesque hack to fix <rdar://problem/4059059> Crash in RenderFlow::detach
3735     // Somehow the PageState object is not properly updated, and is holding onto a stale document.
3736     // Both Xcode and FileMaker see this crash, Safari does not.
3737     
3738     ASSERT(!cachedPage || cachedPage->document() == m_frame->document());
3739     if (cachedPage && cachedPage->document() == m_frame->document())
3740         cachedPage->clear();
3741     
3742     if (m_currentHistoryItem)
3743         m_currentHistoryItem->setCachedPage(0);
3744 }
3745
3746 void FrameLoader::saveDocumentState()
3747 {
3748     if (m_creatingInitialEmptyDocument)
3749         return;
3750
3751     // Do not save doc state if the page has a form that would be submitted via https.
3752     Document* document = m_frame->document();
3753     ASSERT(document);
3754         
3755     if (document->hasSecureForm())
3756          return;
3757          
3758     // For a standard page load, we will have a previous item set, which will be used to
3759     // store the form state.  However, in some cases we will have no previous item, and
3760     // the current item is the right place to save the state.  One example is when we
3761     // detach a bunch of frames because we are navigating from a site with frames to
3762     // another site.  Another is when saving the frame state of a frame that is not the
3763     // target of the current navigation (if we even decide to save with that granularity).
3764
3765     // Because of previousItem's "masking" of currentItem for this purpose, it's important
3766     // that previousItem be cleared at the end of a page transition.  We leverage the
3767     // checkLoadComplete recursion to achieve this goal.
3768
3769     HistoryItem* item = m_previousHistoryItem ? m_previousHistoryItem.get() : m_currentHistoryItem.get();
3770     if (!item)
3771         return;
3772         
3773     if (document) {
3774         LOG(Loading, "WebCoreLoading %s: saving form state to %p", ((String&)m_frame->tree()->name()).ascii().data(), item);
3775         item->setDocumentState(document->formElementsState());
3776     }
3777 }
3778
3779 // Loads content into this frame, as specified by history item
3780 void FrameLoader::loadItem(HistoryItem* item, FrameLoadType loadType)
3781 {
3782     KURL itemURL = item->url();
3783     KURL itemOriginalURL = item->originalURL();
3784     KURL currentURL;
3785     if (documentLoader())
3786         currentURL = documentLoader()->URL();
3787     RefPtr<FormData> formData = item->formData();
3788
3789     // Are we navigating to an anchor within the page?
3790     // Note if we have child frames we do a real reload, since the child frames might not
3791     // match our current frame structure, or they might not have the right content.  We could
3792     // check for all that as an additional optimization.
3793     // We also do not do anchor-style navigation if we're posting a form.
3794     
3795     if (!formData && !shouldReload(itemURL, currentURL) && urlsMatchItem(item)) {
3796         // Must do this maintenance here, since we don't go through a real page reload
3797         saveScrollPositionAndViewStateToItem(m_currentHistoryItem.get());
3798
3799         if (FrameView* view = m_frame->view())
3800             view->setWasScrolledByUser(false);
3801
3802         m_currentHistoryItem = item;
3803
3804         // FIXME: Form state might need to be saved here too.
3805
3806         // We always call scrollToAnchor here, even if the URL doesn't have an
3807         // anchor fragment. This is so we'll keep the WebCore Frame's URL up-to-date.
3808         scrollToAnchor(item->url());
3809     
3810         // must do this maintenance here, since we don't go through a real page reload
3811         restoreScrollPositionAndViewState();
3812         
3813         // Fake the URL change by updating the data source's request.  This will no longer
3814         // be necessary if we do the better fix described above.
3815         documentLoader()->replaceRequestURLForAnchorScroll(itemURL);
3816
3817         dispatchDidChangeLocationWithinPage();
3818         
3819         // FrameLoaderClient::didFinishLoad() tells the internal load delegate the load finished with no error
3820         dispatchDidFinishLoadToClient();
3821     } else {
3822         // Remember this item so we can traverse any child items as child frames load
3823         m_provisionalHistoryItem = item;
3824
3825         bool inPageCache = false;
3826         
3827         // Check if we'll be using the page cache.  We only use the page cache
3828         // if one exists and it is less than _backForwardCacheExpirationInterval
3829         // seconds old.  If the cache is expired it gets flushed here.
3830         if (item->cachedPage()) {
3831             RefPtr<CachedPage> cachedPage = item->cachedPage();
3832             double interval = currentTime() - cachedPage->timeStamp();
3833             
3834             // FIXME: 1800 should not be hardcoded, it should come from
3835             // WebKitBackForwardCacheExpirationIntervalKey in WebKit.
3836             // Or we should remove WebKitBackForwardCacheExpirationIntervalKey.
3837             if (interval <= 1800) {
3838                 load(cachedPage->documentLoader(), loadType, 0);   
3839                 inPageCache = true;
3840             } else {
3841                 LOG(PageCache, "Not restoring page for %s from back/forward cache because cache entry has expired", m_provisionalHistoryItem->url().url().ascii());
3842                 item->setCachedPage(0);
3843             }
3844         }
3845         
3846         if (!inPageCache) {
3847             ResourceRequest request(itemURL);
3848
3849             addExtraFieldsToRequest(request, true, formData);
3850
3851             // If this was a repost that failed the page cache, we might try to repost the form.
3852             NavigationAction action;
3853             if (formData) {
3854                 request.setHTTPMethod("POST");
3855                 request.setHTTPReferrer(item->formReferrer());
3856                 request.setHTTPBody(formData);
3857                 request.setHTTPContentType(item->formContentType());
3858         
3859                 // FIXME: Slight hack to test if the NSURL cache contains the page we're going to.
3860                 // We want to know this before talking to the policy delegate, since it affects whether 
3861                 // we show the DoYouReallyWantToRepost nag.
3862                 //
3863                 // This trick has a small bug (3123893) where we might find a cache hit, but then
3864                 // have the item vanish when we try to use it in the ensuing nav.  This should be
3865                 // extremely rare, but in that case the user will get an error on the navigation.
3866                 
3867                 if (ResourceHandle::willLoadFromCache(request))
3868                     action = NavigationAction(itemURL, loadType, false);
3869                 else {
3870                     request.setCachePolicy(ReloadIgnoringCacheData);
3871                     action = NavigationAction(itemURL, NavigationTypeFormResubmitted);
3872                 }
3873             } else {
3874                 switch (loadType) {
3875                     case FrameLoadTypeReload:
3876                         request.setCachePolicy(ReloadIgnoringCacheData);
3877                         break;
3878                     case FrameLoadTypeBack:
3879                     case FrameLoadTypeForward:
3880                     case FrameLoadTypeIndexedBackForward:
3881                         if (itemURL.protocol() == "https")
3882                             request.setCachePolicy(ReturnCacheDataElseLoad);
3883                         break;
3884                     case FrameLoadTypeStandard:
3885                     case FrameLoadTypeInternal:
3886                         // no-op: leave as protocol default
3887                         // FIXME:  I wonder if we ever hit this case
3888                         break;
3889                     case FrameLoadTypeSame:
3890                     case FrameLoadTypeReloadAllowingStaleData:
3891                     default:
3892                         ASSERT_NOT_REACHED();
3893                 }
3894
3895                 action = NavigationAction(itemOriginalURL, loadType, false);
3896             }
3897
3898             load(request, action, loadType, 0);
3899         }
3900     }
3901 }
3902
3903 // Walk the frame tree and ensure that the URLs match the URLs in the item.
3904 bool FrameLoader::urlsMatchItem(HistoryItem* item) const
3905 {
3906     KURL currentURL = documentLoader()->URL();
3907     
3908     if (!equalIgnoringRef(currentURL, item->url()))
3909         return false;
3910     
3911     const HistoryItemVector& childItems = item->children();
3912     
3913     unsigned size = childItems.size();
3914     for (unsigned i = 0; i < size; ++i) {
3915         Frame* childFrame = m_frame->tree()->child(childItems[i]->target());
3916         if (childFrame && !childFrame->loader()->urlsMatchItem(childItems[i].get()))
3917             return false;
3918     }
3919
3920     return true;
3921 }
3922
3923 // Main funnel for navigating to a previous location (back/forward, non-search snap-back)
3924 // This includes recursion to handle loading into framesets properly
3925 void FrameLoader::goToItem(HistoryItem* targetItem, FrameLoadType type)
3926 {
3927     ASSERT(!m_frame->tree()->parent());
3928     
3929     // shouldGoToHistoryItem is a private delegate method. This is needed to fix:
3930     // <rdar://problem/3951283> can view pages from the back/forward cache that should be disallowed by Parental Controls
3931     // Ultimately, history item navigations should go through the policy delegate. That's covered in:
3932     // <rdar://problem/3979539> back/forward cache navigations should consult policy delegate
3933     if (shouldGoToHistoryItem(targetItem)) {
3934         BackForwardList* bfList = m_frame->page()->backForwardList();
3935         HistoryItem* currentItem = bfList->currentItem();
3936         
3937         // Set the BF cursor before commit, which lets the user quickly click back/forward again.
3938         // - plus, it only makes sense for the top level of the operation through the frametree,
3939         // as opposed to happening for some/one of the page commits that might happen soon
3940         bfList->goToItem(targetItem);
3941         recursiveGoToItem(targetItem, currentItem, type);
3942     }
3943 }
3944
3945 // The general idea here is to traverse the frame tree and the item tree in parallel,
3946 // tracking whether each frame already has the content the item requests.  If there is
3947 // a match (by URL), we just restore scroll position and recurse.  Otherwise we must
3948 // reload that frame, and all its kids.
3949 void FrameLoader::recursiveGoToItem(HistoryItem* item, HistoryItem* fromItem, FrameLoadType type)
3950 {
3951     ASSERT(item);
3952     ASSERT(fromItem);
3953     
3954     KURL itemURL = item->url();
3955     KURL currentURL;
3956     if (documentLoader())
3957         currentURL = documentLoader()->URL();
3958     
3959     // Always reload the target frame of the item we're going to.  This ensures that we will
3960     // do -some- load for the transition, which means a proper notification will be posted
3961     // to the app.
3962     // The exact URL has to match, including fragment.  We want to go through the _load
3963     // method, even if to do a within-page navigation.
3964     // The current frame tree and the frame tree snapshot in the item have to match.
3965     if (!item->isTargetItem() &&
3966         itemURL == currentURL &&
3967         ((m_frame->tree()->name().isEmpty() && item->target().isEmpty()) || m_frame->tree()->name() == item->target()) &&
3968         childFramesMatchItem(item))
3969     {
3970         // This content is good, so leave it alone and look for children that need reloading
3971         // Save form state (works from currentItem, since prevItem is nil)
3972         ASSERT(!m_previousHistoryItem);
3973         saveDocumentState();
3974         saveScrollPositionAndViewStateToItem(m_currentHistoryItem.get());
3975
3976         if (FrameView* view = m_frame->view())
3977             view->setWasScrolledByUser(false);
3978
3979         m_currentHistoryItem = item;
3980                 
3981         // Restore form state (works from currentItem)
3982         restoreDocumentState();
3983         
3984         // Restore the scroll position (we choose to do this rather than going back to the anchor point)
3985         restoreScrollPositionAndViewState();
3986         
3987         const HistoryItemVector& childItems = item->children();
3988         
3989         int size = childItems.size();
3990         for (int i = 0; i < size; ++i) {
3991             String childName = childItems[i]->target();
3992             HistoryItem* fromChildItem = fromItem->childItemWithName(childName);
3993             ASSERT(fromChildItem || fromItem->isTargetItem());
3994             Frame* childFrame = m_frame->tree()->child(childName);
3995             ASSERT(childFrame);
3996             childFrame->loader()->recursiveGoToItem(childItems[i].get(), fromChildItem, type);
3997         }
3998     } else {
3999         loadItem(item, type);
4000     }
4001 }
4002
4003 // helper method that determines whether the subframes described by the item's subitems
4004 // match our own current frameset
4005 bool FrameLoader::childFramesMatchItem(HistoryItem* item) const
4006 {
4007     const HistoryItemVector& childItems = item->children();
4008     if (childItems.size() != m_frame->tree()->childCount())
4009         return false;
4010     
4011     unsigned size = childItems.size();
4012     for (unsigned i = 0; i < size; ++i)
4013         if (!m_frame->tree()->child(childItems[i]->target()))
4014             return false;
4015     
4016     // Found matches for all item targets
4017     return true;
4018 }
4019
4020 void FrameLoader::addHistoryForCurrentLocation()
4021 {
4022     if (!privateBrowsingEnabled()) {
4023         // FIXME: <rdar://problem/4880065> - This will be a hook into the WebCore global history, and this loader/client call will be removed
4024         updateGlobalHistoryForStandardLoad(documentLoader()->urlForHistory());
4025     }
4026     addBackForwardItemClippedAtTarget(true);
4027 }
4028
4029 void FrameLoader::updateHistoryForStandardLoad()
4030 {
4031     LOG(History, "WebCoreHistory: Updating History for Standard Load in frame %s", documentLoader()->URL().url().ascii());
4032
4033     if (!documentLoader()->isClientRedirect()) {
4034         if (!documentLoader()->urlForHistory().isEmpty()) 
4035             addHistoryForCurrentLocation();
4036     } else if (documentLoader()->unreachableURL().isEmpty() && m_currentHistoryItem) {
4037         m_currentHistoryItem->setURL(documentLoader()->URL());
4038         m_currentHistoryItem->setFormInfoFromRequest(documentLoader()->request());
4039     }
4040 }
4041
4042 void FrameLoader::updateHistoryForClientRedirect()
4043 {
4044 #if !LOG_DISABLED
4045     if (documentLoader())
4046         LOG(History, "WebCoreHistory: Updating History for client redirect in frame %s", documentLoader()->title().utf8().data());
4047 #endif
4048
4049     // Clear out form data so we don't try to restore it into the incoming page.  Must happen after
4050     // webcore has closed the URL and saved away the form state.
4051     if (m_currentHistoryItem) {
4052         m_currentHistoryItem->clearDocumentState();
4053         m_currentHistoryItem->clearScrollPoint();
4054     }
4055 }
4056
4057 void FrameLoader::updateHistoryForBackForwardNavigation()
4058 {
4059 #if !LOG_DISABLED
4060     if (documentLoader())
4061         LOG(History, "WebCoreHistory: Updating History for back/forward navigation in frame %s", documentLoader()->title().utf8().data());
4062 #endif
4063
4064     // Must grab the current scroll position before disturbing it
4065     saveScrollPositionAndViewStateToItem(m_previousHistoryItem.get());
4066 }
4067
4068 void FrameLoader::updateHistoryForReload()
4069 {
4070 #if !LOG_DISABLED
4071     if (documentLoader())
4072         LOG(History, "WebCoreHistory: Updating History for reload in frame %s", documentLoader()->title().utf8().data());
4073 #endif
4074
4075     if (m_previousHistoryItem) {
4076         m_previousHistoryItem->setCachedPage(0);
4077     
4078         if (loadType() == FrameLoadTypeReload)
4079             saveScrollPositionAndViewStateToItem(m_previousHistoryItem.get());
4080     
4081         // Sometimes loading a page again leads to a different result because of cookies. Bugzilla 4072
4082         if (documentLoader()->unreachableURL().isEmpty())
4083             m_previousHistoryItem->setURL(documentLoader()->requestURL());
4084     }
4085     
4086     // FIXME: <rdar://problem/4880065> - This will be a hook into the WebCore global history, and this loader/client call will be removed
4087     // Update the last visited time. Mostly interesting for URL autocompletion statistics.
4088     updateGlobalHistoryForReload(documentLoader()->originalURL());
4089 }
4090
4091 void FrameLoader::updateHistoryForInternalLoad()
4092 {
4093 #if !LOG_DISABLED
4094     if (documentLoader())
4095         LOG(History, "WebCoreHistory: Updating History for internal load in frame %s", documentLoader()->title().utf8().data());
4096 #endif
4097     
4098     if (documentLoader()->isClientRedirect()) {
4099         if (!m_currentHistoryItem)
4100             addHistoryForCurrentLocation();
4101             
4102         m_currentHistoryItem->setURL(documentLoader()->URL());
4103         m_currentHistoryItem->setFormInfoFromRequest(documentLoader()->request());
4104     } else {
4105         // Add an item to the item tree for this frame
4106         Frame* parentFrame = m_frame->tree()->parent();
4107         // The only case where parentItem is NULL should be when a parent frame loaded an
4108         // empty URL, which doesn't set up a current item in that parent.
4109         if (parentFrame) {
4110             if (parentFrame->loader()->m_currentHistoryItem)
4111                 parentFrame->loader()->m_currentHistoryItem->addChildItem(createHistoryItem(true));
4112         } else {
4113             // See 3556159. It's not clear if it's valid to be in FrameLoadTypeOnLoadEvent
4114             // for a top-level frame, but that was a likely explanation for those crashes,
4115             // so let's guard against it.
4116             // ...and all FrameLoadTypeOnLoadEvent uses were folded to WebFrameLoadTypeInternal
4117             LOG_ERROR("No parent frame in transitionToCommitted:, FrameLoadTypeInternal");
4118         }
4119     }
4120 }
4121
4122 void FrameLoader::updateHistoryForCommit()
4123 {
4124 #if !LOG_DISABLED
4125     if (documentLoader())
4126         LOG(History, "WebCoreHistory: Updating History for commit in frame %s", documentLoader()->title().utf8().data());
4127 #endif
4128     FrameLoadType type = loadType();
4129     if (isBackForwardLoadType(type) ||
4130         (type == FrameLoadTypeReload && !provisionalDocumentLoader()->unreachableURL().isEmpty())) {
4131         // Once committed, we want to use current item for saving DocState, and
4132         // the provisional item for restoring state.
4133         // Note previousItem must be set before we close the URL, which will
4134         // happen when the data source is made non-provisional below
4135         m_previousHistoryItem = m_currentHistoryItem;
4136         ASSERT(m_provisionalHistoryItem);
4137         m_currentHistoryItem = m_provisionalHistoryItem;
4138         m_provisionalHistoryItem = 0;
4139     }
4140 }
4141
4142 // Walk the frame tree, telling all frames to save their form state into their current
4143 // history item.
4144 void FrameLoader::saveDocumentAndScrollState()
4145 {
4146     for (Frame* frame = m_frame; frame; frame = frame->tree()->traverseNext(m_frame)) {
4147         frame->loader()->saveDocumentState();
4148         frame->loader()->saveScrollPositionAndViewStateToItem(frame->loader()->currentHistoryItem());
4149     }
4150 }
4151
4152 // FIXME: These 6 setter/getters are here for a dwindling number of users in WebKit, WebFrame
4153 // being the primary one.  After they're no longer needed there, they can be removed!
4154 HistoryItem* FrameLoader::currentHistoryItem()
4155 {
4156     return m_currentHistoryItem.get();
4157 }
4158
4159 HistoryItem* FrameLoader::previousHistoryItem()
4160 {
4161     return m_previousHistoryItem.get();
4162 }
4163
4164 HistoryItem* FrameLoader::provisionalHistoryItem()
4165 {
4166     return m_provisionalHistoryItem.get();
4167 }
4168
4169 void FrameLoader::setCurrentHistoryItem(PassRefPtr<HistoryItem> item)
4170 {
4171     m_currentHistoryItem = item;
4172 }
4173
4174 void FrameLoader::setPreviousHistoryItem(PassRefPtr<HistoryItem> item)
4175 {
4176     m_previousHistoryItem = item;
4177 }
4178
4179 void FrameLoader::setProvisionalHistoryItem(PassRefPtr<HistoryItem> item)
4180 {
4181     m_provisionalHistoryItem = item;
4182 }
4183
4184 void FrameLoader::setMainDocumentError(DocumentLoader* loader, const ResourceError& error)
4185 {
4186     m_client->setMainDocumentError(loader, error);
4187 }
4188
4189 void FrameLoader::mainReceivedCompleteError(DocumentLoader* loader, const ResourceError& error)
4190 {
4191     loader->setPrimaryLoadComplete(true);
4192     m_client->dispatchDidLoadMainResource(activeDocumentLoader());
4193     checkCompleted();
4194 #if PLATFORM(QT)
4195     checkLoadComplete();
4196 #endif
4197 }
4198
4199 void FrameLoader::mainReceivedError(const ResourceError& error, bool isComplete)
4200 {
4201     activeDocumentLoader()->mainReceivedError(error, isComplete);
4202 }
4203
4204 ResourceError FrameLoader::cancelledError(const ResourceRequest& request) const
4205 {
4206     return m_client->cancelledError(request);
4207 }
4208
4209 ResourceError FrameLoader::blockedError(const ResourceRequest& request) const
4210 {
4211     return m_client->blockedError(request);
4212 }
4213
4214 ResourceError FrameLoader::fileDoesNotExistError(const ResourceResponse& response) const
4215 {
4216     return m_client->fileDoesNotExistError(response);    
4217 }
4218
4219 void FrameLoader::didFinishLoad(ResourceLoader* loader)
4220 {    
4221     if (m_frame->page())
4222         m_frame->page()->progress()->completeProgress(loader->identifier());
4223     m_client->dispatchDidFinishLoading(loader->documentLoader(), loader->identifier());
4224 }
4225
4226 void FrameLoader::didReceiveAuthenticationChallenge(ResourceLoader* loader, const AuthenticationChallenge& currentWebChallenge)
4227 {
4228     m_client->dispatchDidReceiveAuthenticationChallenge(loader->documentLoader(), loader->identifier(), currentWebChallenge);
4229 }
4230
4231 void FrameLoader::didCancelAuthenticationChallenge(ResourceLoader* loader, const AuthenticationChallenge& currentWebChallenge)
4232 {
4233     m_client->dispatchDidCancelAuthenticationChallenge(loader->documentLoader(), loader->identifier(), currentWebChallenge);
4234 }
4235
4236 PolicyCheck::PolicyCheck()
4237     : m_navigationFunction(0)
4238     , m_newWindowFunction(0)
4239     , m_contentFunction(0)
4240 {
4241 }
4242
4243 void PolicyCheck::clear()
4244 {
4245     clearRequest();
4246     m_navigationFunction = 0;
4247     m_newWindowFunction = 0;
4248     m_contentFunction = 0;
4249 }
4250
4251 void PolicyCheck::set(const ResourceRequest& request, PassRefPtr<FormState> formState,
4252     NavigationPolicyDecisionFunction function, void* argument)
4253 {
4254     m_request = request;
4255     m_formState = formState;
4256     m_frameName = String();
4257
4258     m_navigationFunction = function;
4259     m_newWindowFunction = 0;
4260     m_contentFunction = 0;
4261     m_argument = argument;
4262 }
4263
4264 void PolicyCheck::set(const ResourceRequest& request, PassRefPtr<FormState> formState,
4265     const String& frameName, NewWindowPolicyDecisionFunction function, void* argument)