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