Reviewed by Hyatt.
[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     if (!m_frame->document()->haveStylesheetsLoaded()) {
1416         m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(true);
1417         return false;
1418     }
1419
1420     m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(false);
1421
1422     Node* anchorNode = m_frame->document()->getElementById(AtomicString(name));
1423     if (!anchorNode)
1424         anchorNode = m_frame->document()->anchors()->namedItem(name, !m_frame->document()->inCompatMode());
1425
1426     m_frame->document()->setCSSTarget(anchorNode); // Setting to null will clear the current target.
1427   
1428     // Implement the rule that "" and "top" both mean top of page as in other browsers.
1429     if (!anchorNode && !(name.isEmpty() || equalIgnoringCase(name, "top")))
1430         return false;
1431
1432     // We need to update the layout before scrolling, otherwise we could
1433     // really mess things up if an anchor scroll comes at a bad moment.
1434     if (m_frame->document()) {
1435         m_frame->document()->updateRendering();
1436         // Only do a layout if changes have occurred that make it necessary.      
1437         if (m_frame->view() && m_frame->document()->renderer() && m_frame->document()->renderer()->needsLayout())
1438             m_frame->view()->layout();
1439     }
1440   
1441     // Scroll nested layers and frames to reveal the anchor.
1442     // Align to the top and to the closest side (this matches other browsers).
1443     RenderObject* renderer;
1444     IntRect rect;
1445     if (!anchorNode)
1446         renderer = m_frame->document()->renderer(); // top of document
1447     else {
1448         renderer = anchorNode->renderer();
1449         rect = anchorNode->getRect();
1450     }
1451     if (renderer)
1452         renderer->enclosingLayer()->scrollRectToVisible(rect, RenderLayer::gAlignToEdgeIfNeeded, RenderLayer::gAlignTopAlways);
1453
1454     return true;
1455 }
1456
1457 bool FrameLoader::requestObject(RenderPart* renderer, const String& url, const AtomicString& frameName,
1458     const String& mimeType, const Vector<String>& paramNames, const Vector<String>& paramValues)
1459 {
1460     if (url.isEmpty() && mimeType.isEmpty())
1461         return true;
1462
1463 #if USE(LOW_BANDWIDTH_DISPLAY)
1464     // don't care object during low bandwidth display
1465     if (frame()->document()->inLowBandwidthDisplay()) {
1466         m_needToSwitchOutLowBandwidthDisplay = true;
1467         return false;
1468     }
1469 #endif
1470
1471     KURL completedURL;
1472     if (!url.isEmpty())
1473         completedURL = completeURL(url);
1474
1475     bool useFallback;
1476     if (shouldUsePlugin(completedURL, mimeType, renderer->hasFallbackContent(), useFallback)) {
1477         Settings* settings = m_frame->settings();
1478         if (!settings || !settings->arePluginsEnabled() || 
1479             (!settings->isJavaEnabled() && MIMETypeRegistry::isJavaAppletMIMEType(mimeType)))
1480             return false;
1481         return loadPlugin(renderer, completedURL, mimeType, paramNames, paramValues, useFallback);
1482     }
1483
1484     ASSERT(renderer->node()->hasTagName(objectTag) || renderer->node()->hasTagName(embedTag));
1485     HTMLPlugInElement* element = static_cast<HTMLPlugInElement*>(renderer->node());
1486
1487     AtomicString uniqueFrameName = m_frame->tree()->uniqueChildName(frameName);
1488     element->setFrameName(uniqueFrameName);
1489     
1490     // FIXME: OK to always make a new frame? When does the old frame get removed?
1491     return loadSubframe(element, completedURL, uniqueFrameName, m_outgoingReferrer);
1492 }
1493
1494 bool FrameLoader::shouldUsePlugin(const KURL& url, const String& mimeType, bool hasFallback, bool& useFallback)
1495 {
1496     ObjectContentType objectType = m_client->objectContentType(url, mimeType);
1497     // If an object's content can't be handled and it has no fallback, let
1498     // it be handled as a plugin to show the broken plugin icon.
1499     useFallback = objectType == ObjectContentNone && hasFallback;
1500     return objectType == ObjectContentNone || objectType == ObjectContentPlugin;
1501 }
1502
1503 bool FrameLoader::loadPlugin(RenderPart* renderer, const KURL& url, const String& mimeType, 
1504     const Vector<String>& paramNames, const Vector<String>& paramValues, bool useFallback)
1505 {
1506     Widget* widget = 0;
1507
1508     if (renderer && !useFallback) {
1509         Element* pluginElement = 0;
1510         if (renderer->node() && renderer->node()->isElementNode())
1511             pluginElement = static_cast<Element*>(renderer->node());
1512
1513         if (!canLoad(url, frame()->document())) {
1514             FrameLoader::reportLocalLoadFailed(m_frame->page(), url.url());
1515             return false;
1516         }
1517
1518         widget = m_client->createPlugin(pluginElement, url, paramNames, paramValues, mimeType,
1519                                         m_frame->document()->isPluginDocument());
1520         if (widget) {
1521             renderer->setWidget(widget);
1522             m_containsPlugIns = true;
1523         }
1524     }
1525
1526     checkCallImplicitClose();
1527     return widget != 0;
1528 }
1529
1530 void FrameLoader::clearRecordedFormValues()
1531 {
1532     m_formAboutToBeSubmitted = 0;
1533     m_formValuesAboutToBeSubmitted.clear();
1534 }
1535
1536 void FrameLoader::recordFormValue(const String& name, const String& value, PassRefPtr<HTMLFormElement> element)
1537 {
1538     m_formAboutToBeSubmitted = element;
1539     m_formValuesAboutToBeSubmitted.set(name, value);
1540 }
1541
1542 void FrameLoader::parentCompleted()
1543 {
1544     if (m_scheduledRedirection && !m_redirectionTimer.isActive())
1545         startRedirectionTimer();
1546 }
1547
1548 String FrameLoader::outgoingReferrer() const
1549 {
1550     return m_outgoingReferrer;
1551 }
1552
1553 Frame* FrameLoader::opener()
1554 {
1555     return m_opener;
1556 }
1557
1558 void FrameLoader::setOpener(Frame* opener)
1559 {
1560     if (m_opener)
1561         m_opener->loader()->m_openedFrames.remove(m_frame);
1562     if (opener)
1563         opener->loader()->m_openedFrames.add(m_frame);
1564     m_opener = opener;
1565 }
1566
1567 bool FrameLoader::openedByDOM() const
1568 {
1569     return m_openedByDOM;
1570 }
1571
1572 void FrameLoader::setOpenedByDOM()
1573 {
1574     m_openedByDOM = true;
1575 }
1576
1577 void FrameLoader::handleFallbackContent()
1578 {
1579     HTMLFrameOwnerElement* owner = m_frame->ownerElement();
1580     if (!owner || !owner->hasTagName(objectTag))
1581         return;
1582     static_cast<HTMLObjectElement*>(owner)->renderFallbackContent();
1583 }
1584
1585 void FrameLoader::provisionalLoadStarted()
1586 {
1587     m_firstLayoutDone = false;
1588     cancelRedirection(true);
1589     m_client->provisionalLoadStarted();
1590
1591     if (canCachePage() && m_client->canCachePage() && !m_currentHistoryItem->isInPageCache())
1592         cachePageForHistoryItem(m_currentHistoryItem.get());
1593 }
1594
1595 bool FrameLoader::userGestureHint()
1596 {
1597     Frame* rootFrame = m_frame;
1598     while (rootFrame->tree()->parent())
1599         rootFrame = rootFrame->tree()->parent();
1600
1601     if (rootFrame->scriptProxy())
1602         return rootFrame->scriptProxy()->interpreter()->wasRunByUserGesture();
1603
1604     return true; // If JavaScript is disabled, a user gesture must have initiated the navigation
1605 }
1606
1607 void FrameLoader::didNotOpenURL(const KURL& URL)
1608 {
1609     if (m_submittedFormURL == URL)
1610         m_submittedFormURL = KURL();
1611 }
1612
1613 void FrameLoader::resetMultipleFormSubmissionProtection()
1614 {
1615     m_submittedFormURL = KURL();
1616 }
1617
1618 void FrameLoader::setEncoding(const String& name, bool userChosen)
1619 {
1620     if (!m_workingURL.isEmpty())
1621         receivedFirstData();
1622     m_encoding = name;
1623     m_encodingWasChosenByUser = userChosen;
1624 }
1625
1626 void FrameLoader::addData(const char* bytes, int length)
1627 {
1628     ASSERT(m_workingURL.isEmpty());
1629     ASSERT(m_frame->document());
1630     ASSERT(m_frame->document()->parsing());
1631     write(bytes, length);
1632 }
1633
1634 bool FrameLoader::canCachePage()
1635 {    
1636     // Cache the page, if possible.
1637     // Don't write to the cache if in the middle of a redirect, since we will want to
1638     // store the final page we end up on.
1639     // No point writing to the cache on a reload or loadSame, since we will just write
1640     // over it again when we leave that page.
1641     // FIXME: <rdar://problem/4886592> - We should work out the complexities of caching pages with frames as they
1642     // are the most interesting pages on the web, and often those that would benefit the most from caching!
1643     FrameLoadType loadType = this->loadType();
1644
1645     return m_documentLoader
1646         && m_documentLoader->mainDocumentError().isNull()
1647         && !m_frame->tree()->childCount()
1648         && !m_frame->tree()->parent()
1649         && !m_containsPlugIns
1650         && !m_URL.protocol().startsWith("https")
1651         && m_frame->document()
1652         && !m_frame->document()->applets()->length()
1653         && !m_frame->document()->hasWindowEventListener(unloadEvent)
1654         && m_frame->page()
1655         && m_frame->page()->backForwardList()->enabled()
1656         && m_frame->page()->backForwardList()->capacity() > 0
1657         && m_frame->page()->settings()->usesPageCache()
1658         && m_currentHistoryItem
1659         && !isQuickRedirectComing()
1660         && loadType != FrameLoadTypeReload 
1661         && loadType != FrameLoadTypeReloadAllowingStaleData
1662         && loadType != FrameLoadTypeSame
1663         && !m_documentLoader->isLoadingInAPISense()
1664         && !m_documentLoader->isStopping();
1665 }
1666
1667 void FrameLoader::updatePolicyBaseURL()
1668 {
1669     if (m_frame->tree()->parent() && m_frame->tree()->parent()->document())
1670         setPolicyBaseURL(m_frame->tree()->parent()->document()->policyBaseURL());
1671     else
1672         setPolicyBaseURL(m_URL.url());
1673 }
1674
1675 void FrameLoader::setPolicyBaseURL(const String& s)
1676 {
1677     if (m_frame->document())
1678         m_frame->document()->setPolicyBaseURL(s);
1679     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
1680         child->loader()->setPolicyBaseURL(s);
1681 }
1682
1683 // This does the same kind of work that FrameLoader::openURL does, except it relies on the fact
1684 // that a higher level already checked that the URLs match and the scrolling is the right thing to do.
1685 void FrameLoader::scrollToAnchor(const KURL& URL)
1686 {
1687     m_URL = URL;
1688     started();
1689
1690     gotoAnchor();
1691
1692     // It's important to model this as a load that starts and immediately finishes.
1693     // Otherwise, the parent frame may think we never finished loading.
1694     m_isComplete = false;
1695     checkCompleted();
1696 }
1697
1698 bool FrameLoader::isComplete() const
1699 {
1700     return m_isComplete;
1701 }
1702
1703 void FrameLoader::scheduleRedirection(ScheduledRedirection* redirection)
1704 {
1705     stopRedirectionTimer();
1706     m_scheduledRedirection.set(redirection);
1707     if (m_isComplete)
1708         startRedirectionTimer();
1709 }
1710
1711 void FrameLoader::startRedirectionTimer()
1712 {
1713     ASSERT(m_scheduledRedirection);
1714
1715     m_redirectionTimer.stop();
1716     m_redirectionTimer.startOneShot(m_scheduledRedirection->delay);
1717
1718     switch (m_scheduledRedirection->type) {
1719         case ScheduledRedirection::redirection:
1720         case ScheduledRedirection::locationChange:
1721         case ScheduledRedirection::locationChangeDuringLoad:
1722             clientRedirected(m_scheduledRedirection->URL.deprecatedString(),
1723                 m_scheduledRedirection->delay,
1724                 currentTime() + m_redirectionTimer.nextFireInterval(),
1725                 m_scheduledRedirection->lockHistory,
1726                 m_isExecutingJavaScriptFormAction);
1727             return;
1728         case ScheduledRedirection::historyNavigation:
1729             // Don't report history navigations.
1730             return;
1731     }
1732     ASSERT_NOT_REACHED();
1733 }
1734
1735 void FrameLoader::stopRedirectionTimer()
1736 {
1737     if (!m_redirectionTimer.isActive())
1738         return;
1739
1740     m_redirectionTimer.stop();
1741
1742     if (m_scheduledRedirection) {
1743         switch (m_scheduledRedirection->type) {
1744             case ScheduledRedirection::redirection:
1745             case ScheduledRedirection::locationChange:
1746             case ScheduledRedirection::locationChangeDuringLoad:
1747                 clientRedirectCancelledOrFinished(m_cancellingWithLoadInProgress);
1748                 return;
1749             case ScheduledRedirection::historyNavigation:
1750                 // Don't report history navigations.
1751                 return;
1752         }
1753         ASSERT_NOT_REACHED();
1754     }
1755 }
1756
1757 void FrameLoader::completed()
1758 {
1759     RefPtr<Frame> protect(m_frame);
1760     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
1761         child->loader()->parentCompleted();
1762     if (Frame* parent = m_frame->tree()->parent())
1763         parent->loader()->checkCompleted();
1764     submitFormAgain();
1765 }
1766
1767 void FrameLoader::started()
1768 {
1769     for (Frame* frame = m_frame; frame; frame = frame->tree()->parent())
1770         frame->loader()->m_isComplete = false;
1771 }
1772
1773 bool FrameLoader::containsPlugins() const 
1774
1775     return m_containsPlugIns;
1776 }
1777
1778 void FrameLoader::prepareForLoadStart()
1779 {
1780     if (Page* page = m_frame->page())
1781         page->progress()->progressStarted(m_frame);
1782     m_client->dispatchDidStartProvisionalLoad();
1783 }
1784
1785 void FrameLoader::setupForReplace()
1786 {
1787     setState(FrameStateProvisional);
1788     m_provisionalDocumentLoader = m_documentLoader;
1789     m_documentLoader = 0;
1790     detachChildren();
1791 }
1792
1793 void FrameLoader::setupForReplaceByMIMEType(const String& newMIMEType)
1794 {
1795     activeDocumentLoader()->setupForReplaceByMIMEType(newMIMEType);
1796 }
1797
1798 void FrameLoader::finalSetupForReplace(DocumentLoader* loader)
1799 {
1800     m_client->clearUnarchivingState(loader);
1801 }
1802
1803 void FrameLoader::load(const KURL& URL, Event* event)
1804 {
1805     load(ResourceRequest(URL), false, true, event, 0, HashMap<String, String>());
1806 }
1807
1808 void FrameLoader::load(const FrameLoadRequest& request, bool lockHistory, bool userGesture, Event* event,
1809     HTMLFormElement* submitForm, const HashMap<String, String>& formValues)
1810 {
1811     KURL url = request.resourceRequest().url();
1812  
1813     String referrer;
1814     String argsReferrer = request.resourceRequest().httpReferrer();
1815     if (!argsReferrer.isEmpty())
1816         referrer = argsReferrer;
1817     else
1818         referrer = m_outgoingReferrer;
1819  
1820     ASSERT(frame()->document());
1821     if (!canLoad(url, frame()->document()) &&
1822         !canLoad(url, referrer)) {
1823         FrameLoader::reportLocalLoadFailed(m_frame->page(), url.url());
1824         return;
1825     }
1826
1827     if (shouldHideReferrer(url, referrer))
1828         referrer = String();
1829     
1830     Frame* targetFrame = m_frame->tree()->find(request.frameName());
1831     if (!canTarget(targetFrame))
1832         return;
1833         
1834     if (request.resourceRequest().httpMethod() != "POST") {
1835         FrameLoadType loadType;
1836         if (request.resourceRequest().cachePolicy() == ReloadIgnoringCacheData)
1837             loadType = FrameLoadTypeReload;
1838         else if (lockHistory)
1839             loadType = FrameLoadTypeRedirectWithLockedHistory;
1840         else
1841             loadType = FrameLoadTypeStandard;    
1842     
1843         RefPtr<FormState> formState;
1844         if (submitForm && !formValues.isEmpty())
1845             formState = FormState::create(submitForm, formValues, m_frame);
1846         
1847         load(request.resourceRequest().url(), referrer, loadType, 
1848             request.frameName(), event, formState.release());
1849     } else
1850         post(request.resourceRequest().url(), referrer, request.frameName(), 
1851             request.resourceRequest().httpBody(), request.resourceRequest().httpContentType(), event, submitForm, formValues);
1852
1853     if (targetFrame && targetFrame != m_frame)
1854         if (Page* page = targetFrame->page())
1855             page->chrome()->focus();
1856 }
1857
1858 void FrameLoader::load(const KURL& URL, const String& referrer, FrameLoadType newLoadType,
1859     const String& frameName, Event* event, PassRefPtr<FormState> formState)
1860 {
1861     bool isFormSubmission = formState;
1862     
1863     ResourceRequest request(URL);
1864     if (!referrer.isEmpty())
1865         request.setHTTPReferrer(referrer);
1866     addExtraFieldsToRequest(request, true, event || isFormSubmission);
1867     if (newLoadType == FrameLoadTypeReload)
1868         request.setCachePolicy(ReloadIgnoringCacheData);
1869
1870     ASSERT(newLoadType != FrameLoadTypeSame);
1871
1872     NavigationAction action(URL, newLoadType, isFormSubmission, event);
1873
1874     if (!frameName.isEmpty()) {
1875         if (Frame* targetFrame = m_frame->tree()->find(frameName))
1876             targetFrame->loader()->load(URL, referrer, newLoadType, String(), event, formState);
1877         else
1878             checkNewWindowPolicy(action, request, formState, frameName);
1879         return;
1880     }
1881
1882     RefPtr<DocumentLoader> oldDocumentLoader = m_documentLoader;
1883
1884     bool sameURL = shouldTreatURLAsSameAsCurrent(URL);
1885     
1886     // Make sure to do scroll to anchor processing even if the URL is
1887     // exactly the same so pages with '#' links and DHTML side effects
1888     // work properly.
1889     if (!isFormSubmission
1890         && newLoadType != FrameLoadTypeReload
1891         && newLoadType != FrameLoadTypeSame
1892         && !shouldReload(URL, url())
1893         // We don't want to just scroll if a link from within a
1894         // frameset is trying to reload the frameset into _top.
1895         && !m_frame->isFrameSet()) {
1896
1897         // Just do anchor navigation within the existing content.
1898         
1899         // We don't do this if we are submitting a form, explicitly reloading,
1900         // currently displaying a frameset, or if the new URL does not have a fragment.
1901         // These rules are based on what KHTML was doing in KHTMLPart::openURL.
1902         
1903         // FIXME: What about load types other than Standard and Reload?
1904         
1905         oldDocumentLoader->setTriggeringAction(action);
1906         stopPolicyCheck();
1907         checkNavigationPolicy(request, oldDocumentLoader.get(), formState,
1908             callContinueFragmentScrollAfterNavigationPolicy, this);
1909     } else {
1910         // must grab this now, since this load may stop the previous load and clear this flag
1911         bool isRedirect = m_quickRedirectComing;
1912         load(request, action, newLoadType, formState);
1913         if (isRedirect) {
1914             m_quickRedirectComing = false;
1915             if (m_provisionalDocumentLoader)
1916                 m_provisionalDocumentLoader->setIsClientRedirect(true);
1917         } else if (sameURL)
1918             // Example of this case are sites that reload the same URL with a different cookie
1919             // driving the generated content, or a master frame with links that drive a target
1920             // frame, where the user has clicked on the same link repeatedly.
1921             m_loadType = FrameLoadTypeSame;
1922     }
1923 }
1924
1925 void FrameLoader::load(const ResourceRequest& request)
1926 {
1927     load(request, SubstituteData());
1928 }
1929
1930 void FrameLoader::load(const ResourceRequest& request, const SubstituteData& substituteData)
1931 {
1932     if (m_inStopAllLoaders)
1933         return;
1934         
1935     // FIXME: is this the right place to reset loadType? Perhaps this should be done after loading is finished or aborted.
1936     m_loadType = FrameLoadTypeStandard;
1937     load(m_client->createDocumentLoader(request, substituteData).get());
1938 }
1939
1940 void FrameLoader::load(const ResourceRequest& request, const String& frameName)
1941 {
1942     if (frameName.isEmpty()) {
1943         load(request);
1944         return;
1945     }
1946
1947     Frame* frame = m_frame->tree()->find(frameName);
1948     if (frame) {
1949         frame->loader()->load(request);
1950         return;
1951     }
1952
1953     checkNewWindowPolicy(NavigationAction(request.url(), NavigationTypeOther), request, 0, frameName);
1954 }
1955
1956 void FrameLoader::load(const ResourceRequest& request, const NavigationAction& action, FrameLoadType type, PassRefPtr<FormState> formState)
1957 {
1958     RefPtr<DocumentLoader> loader = m_client->createDocumentLoader(request, SubstituteData());
1959
1960     loader->setTriggeringAction(action);
1961     if (m_documentLoader)
1962         loader->setOverrideEncoding(m_documentLoader->overrideEncoding());
1963
1964     load(loader.get(), type, formState);
1965 }
1966
1967 void FrameLoader::load(DocumentLoader* newDocumentLoader)
1968 {
1969     ResourceRequest& r = newDocumentLoader->request();
1970     addExtraFieldsToRequest(r, true, false);
1971     FrameLoadType type;
1972
1973     if (shouldTreatURLAsSameAsCurrent(newDocumentLoader->originalRequest().url())) {
1974         r.setCachePolicy(ReloadIgnoringCacheData);
1975         type = FrameLoadTypeSame;
1976     } else
1977         type = FrameLoadTypeStandard;
1978
1979     if (m_documentLoader)
1980         newDocumentLoader->setOverrideEncoding(m_documentLoader->overrideEncoding());
1981     
1982     // When we loading alternate content for an unreachable URL that we're
1983     // visiting in the b/f list, we treat it as a reload so the b/f list 
1984     // is appropriately maintained.
1985     if (shouldReloadToHandleUnreachableURL(newDocumentLoader)) {
1986         ASSERT(type == FrameLoadTypeStandard);
1987         type = FrameLoadTypeReload;
1988     }
1989
1990     load(newDocumentLoader, type, 0);
1991 }
1992
1993 void FrameLoader::load(DocumentLoader* loader, FrameLoadType type, PassRefPtr<FormState> formState)
1994 {
1995     ASSERT(m_client->hasWebView());
1996
1997     // Unfortunately the view must be non-nil, this is ultimately due
1998     // to parser requiring a FrameView.  We should fix this dependency.
1999
2000     ASSERT(m_client->hasFrameView());
2001
2002     m_policyLoadType = type;
2003
2004     if (Frame* parent = m_frame->tree()->parent())
2005         loader->setOverrideEncoding(parent->loader()->documentLoader()->overrideEncoding());
2006
2007     stopPolicyCheck();
2008     setPolicyDocumentLoader(loader);
2009
2010     checkNavigationPolicy(loader->request(), loader, formState,
2011         callContinueLoadAfterNavigationPolicy, this);
2012 }
2013
2014 // FIXME: It would be nice if we could collapse these into one or two functions.
2015 bool FrameLoader::canLoad(const KURL& url, const String& referrer)
2016 {
2017     if (!shouldTreatURLAsLocal(url.url()))
2018         return true;
2019
2020     return shouldTreatURLAsLocal(referrer);
2021 }
2022
2023 bool FrameLoader::canLoad(const KURL& url, const Document* doc)
2024 {
2025     if (!shouldTreatURLAsLocal(url.url()))
2026         return true;
2027
2028     return doc && doc->isAllowedToLoadLocalResources();
2029 }
2030
2031 bool FrameLoader::canLoad(const CachedResource& resource, const Document* doc)
2032 {
2033     if (!resource.treatAsLocal())
2034         return true;
2035
2036     return doc && doc->isAllowedToLoadLocalResources();
2037 }
2038
2039 void FrameLoader::reportLocalLoadFailed(const Page* page, const String& url)
2040 {
2041     ASSERT(!url.isEmpty());
2042     if (page)
2043         page->chrome()->addMessageToConsole(JSMessageSource, ErrorMessageLevel, "Not allowed to load local resource: " + url, 0, String());
2044 }
2045
2046 bool FrameLoader::shouldHideReferrer(const KURL& url, const String& referrer)
2047 {
2048     bool referrerIsSecureURL = referrer.startsWith("https:", false);
2049     bool referrerIsWebURL = referrerIsSecureURL || referrer.startsWith("http:", false);
2050
2051     if (!referrerIsWebURL)
2052         return true;
2053
2054     if (!referrerIsSecureURL)
2055         return false;
2056
2057     bool URLIsSecureURL = url.url().startsWith("https:", false);
2058
2059     return !URLIsSecureURL;
2060 }
2061
2062 const ResourceRequest& FrameLoader::initialRequest() const
2063 {
2064     return activeDocumentLoader()->initialRequest();
2065 }
2066
2067 void FrameLoader::receivedData(const char* data, int length)
2068 {
2069     activeDocumentLoader()->receivedData(data, length);
2070 }
2071
2072 bool FrameLoader::willUseArchive(ResourceLoader* loader, const ResourceRequest& request, const KURL& originalURL) const
2073 {
2074     return m_client->willUseArchive(loader, request, originalURL);
2075 }
2076
2077 void FrameLoader::handleUnimplementablePolicy(const ResourceError& error)
2078 {
2079     m_delegateIsHandlingUnimplementablePolicy = true;
2080     m_client->dispatchUnableToImplementPolicy(error);
2081     m_delegateIsHandlingUnimplementablePolicy = false;
2082 }
2083
2084 void FrameLoader::cannotShowMIMEType(const ResourceResponse& response)
2085 {
2086     handleUnimplementablePolicy(m_client->cannotShowMIMETypeError(response));
2087 }
2088
2089 ResourceError FrameLoader::interruptionForPolicyChangeError(const ResourceRequest& request)
2090 {
2091     return m_client->interruptForPolicyChangeError(request);
2092 }
2093
2094 void FrameLoader::checkNavigationPolicy(const ResourceRequest& newRequest, NavigationPolicyDecisionFunction function, void* argument)
2095 {
2096     checkNavigationPolicy(newRequest, activeDocumentLoader(), 0, function, argument);
2097 }
2098
2099 void FrameLoader::checkContentPolicy(const String& MIMEType, ContentPolicyDecisionFunction function, void* argument)
2100 {
2101     ASSERT(activeDocumentLoader());
2102     
2103     // Always show content with valid substitute data.
2104     if (activeDocumentLoader()->substituteData().isValid()) {
2105         function(argument, PolicyUse);
2106         return;
2107     }
2108
2109 #if ENABLE(FTPDIR)
2110     // Respect the hidden FTP Directory Listing pref so it can be tested even if the policy delegate might otherwise disallow it
2111     Settings* settings = m_frame->settings();
2112     if (settings && settings->forceFTPDirectoryListings() && MIMEType == "application/x-ftp-directory") {
2113         function(argument, PolicyUse);
2114         return;
2115     }
2116 #endif
2117
2118     m_policyCheck.set(function, argument);
2119     m_client->dispatchDecidePolicyForMIMEType(&FrameLoader::continueAfterContentPolicy,
2120         MIMEType, activeDocumentLoader()->request());
2121 }
2122
2123 bool FrameLoader::shouldReloadToHandleUnreachableURL(DocumentLoader* docLoader)
2124 {
2125     KURL unreachableURL = docLoader->unreachableURL();
2126
2127     if (unreachableURL.isEmpty())
2128         return false;
2129
2130     if (!isBackForwardLoadType(m_policyLoadType))
2131         return false;
2132
2133     // We only treat unreachableURLs specially during the delegate callbacks
2134     // for provisional load errors and navigation policy decisions. The former
2135     // case handles well-formed URLs that can't be loaded, and the latter
2136     // case handles malformed URLs and unknown schemes. Loading alternate content
2137     // at other times behaves like a standard load.
2138     DocumentLoader* compareDocumentLoader = 0;
2139     if (m_delegateIsDecidingNavigationPolicy || m_delegateIsHandlingUnimplementablePolicy)
2140         compareDocumentLoader = m_policyDocumentLoader.get();
2141     else if (m_delegateIsHandlingProvisionalLoadError)
2142         compareDocumentLoader = m_provisionalDocumentLoader.get();
2143
2144     return compareDocumentLoader && unreachableURL == compareDocumentLoader->request().url();
2145 }
2146
2147 void FrameLoader::reloadAllowingStaleData(const String& encoding)
2148 {
2149     if (!m_documentLoader)
2150         return;
2151
2152     ResourceRequest request = m_documentLoader->request();
2153     KURL unreachableURL = m_documentLoader->unreachableURL();
2154     if (!unreachableURL.isEmpty())
2155         request.setURL(unreachableURL);
2156
2157     request.setCachePolicy(ReturnCacheDataElseLoad);
2158
2159     RefPtr<DocumentLoader> loader = m_client->createDocumentLoader(request, SubstituteData());
2160     setPolicyDocumentLoader(loader.get());
2161
2162     loader->setOverrideEncoding(encoding);
2163
2164     load(loader.get(), FrameLoadTypeReloadAllowingStaleData, 0);
2165 }
2166
2167 void FrameLoader::reload()
2168 {
2169     if (!m_documentLoader)
2170         return;
2171
2172     ResourceRequest& initialRequest = m_documentLoader->request();
2173     
2174     // If a window is created by javascript, its main frame can have an empty but non-nil URL.
2175     // Reloading in this case will lose the current contents (see 4151001).
2176     if (initialRequest.url().isEmpty())
2177         return;
2178
2179     // Replace error-page URL with the URL we were trying to reach.
2180     KURL unreachableURL = m_documentLoader->unreachableURL();
2181     if (!unreachableURL.isEmpty())
2182         initialRequest = ResourceRequest(unreachableURL);
2183     
2184     RefPtr<DocumentLoader> loader = m_client->createDocumentLoader(initialRequest, SubstituteData());
2185
2186     ResourceRequest& request = loader->request();
2187
2188     request.setCachePolicy(ReloadIgnoringCacheData);
2189     request.setHTTPHeaderField("Cache-Control", "max-age=0");
2190
2191     // If we're about to re-post, set up action so the application can warn the user.
2192     if (request.httpMethod() == "POST")
2193         loader->setTriggeringAction(NavigationAction(request.url(), NavigationTypeFormResubmitted));
2194
2195     loader->setOverrideEncoding(m_documentLoader->overrideEncoding());
2196     
2197     load(loader.get(), FrameLoadTypeReload, 0);
2198 }
2199
2200 bool FrameLoader::canTarget(Frame* target) const
2201 {
2202     // This function prevents this exploit:
2203     // <rdar://problem/3715785> multiple frame injection vulnerability reported by Secunia, affects almost all browsers
2204
2205     // Allow if there is no specific target.
2206     if (!target)
2207         return true;
2208
2209     // Allow navigation within the same page/frameset.
2210     if (m_frame->page() == target->page())
2211         return true;
2212
2213     // Allow if the request is made from a local file.
2214     ASSERT(m_frame->document());
2215     String domain = m_frame->document()->domain();
2216     if (domain.isEmpty())
2217         return true;
2218     
2219     // Allow if target is an entire window (top level frame of a window).
2220     Frame* parent = target->tree()->parent();
2221     if (!parent)
2222         return true;
2223     
2224     // Allow if the domain of the parent of the targeted frame equals this domain.
2225     String parentDomain;
2226     if (Document* parentDocument = parent->document())
2227         domain = parentDocument->domain();
2228     return equalIgnoringCase(parentDomain, domain);
2229 }
2230
2231 void FrameLoader::stopLoadingSubframes()
2232 {
2233     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
2234         child->loader()->stopAllLoaders();
2235 }
2236
2237 void FrameLoader::stopAllLoaders()
2238 {
2239     // If this method is called from within this method, infinite recursion can occur (3442218). Avoid this.
2240     if (m_inStopAllLoaders)
2241         return;
2242
2243     m_inStopAllLoaders = true;
2244
2245     stopPolicyCheck();
2246
2247     stopLoadingSubframes();
2248     if (m_provisionalDocumentLoader)
2249         m_provisionalDocumentLoader->stopLoading();
2250     if (m_documentLoader)
2251         m_documentLoader->stopLoading();
2252     setProvisionalDocumentLoader(0);
2253     m_client->clearArchivedResources();
2254
2255     m_inStopAllLoaders = false;    
2256 }
2257
2258 void FrameLoader::stopForUserCancel()
2259 {
2260     stopAllLoaders();
2261     if (m_frame->page())
2262         checkLoadComplete();
2263 }
2264
2265 void FrameLoader::cancelPendingArchiveLoad(ResourceLoader* loader)
2266 {
2267     m_client->cancelPendingArchiveLoad(loader);
2268 }
2269
2270 DocumentLoader* FrameLoader::activeDocumentLoader() const
2271 {
2272     if (m_state == FrameStateProvisional)
2273         return m_provisionalDocumentLoader.get();
2274     return m_documentLoader.get();
2275 }
2276
2277 bool FrameLoader::isLoading() const
2278 {
2279     DocumentLoader* docLoader = activeDocumentLoader();
2280     if (!docLoader)
2281         return false;
2282     return docLoader->isLoadingMainResource() || docLoader->isLoadingSubresources() || docLoader->isLoadingPlugIns();
2283 }
2284
2285 bool FrameLoader::frameHasLoaded() const
2286 {
2287     return m_committedFirstRealDocumentLoad || (m_provisionalDocumentLoader && !m_creatingInitialEmptyDocument); 
2288 }
2289
2290 void FrameLoader::setDocumentLoader(DocumentLoader* loader)
2291 {
2292     if (!loader && !m_documentLoader)
2293         return;
2294     
2295     ASSERT(loader != m_documentLoader);
2296     ASSERT(!loader || loader->frameLoader() == this);
2297
2298     m_client->prepareForDataSourceReplacement();
2299     detachChildren();
2300     if (m_documentLoader)
2301         m_documentLoader->detachFromFrame();
2302
2303     m_documentLoader = loader;
2304 }
2305
2306 DocumentLoader* FrameLoader::documentLoader() const
2307 {
2308     return m_documentLoader.get();
2309 }
2310
2311 void FrameLoader::setPolicyDocumentLoader(DocumentLoader* loader)
2312 {
2313     if (m_policyDocumentLoader == loader)
2314         return;
2315
2316     ASSERT(m_frame);
2317     if (loader)
2318         loader->setFrame(m_frame);
2319     if (m_policyDocumentLoader
2320             && m_policyDocumentLoader != m_provisionalDocumentLoader
2321             && m_policyDocumentLoader != m_documentLoader)
2322         m_policyDocumentLoader->detachFromFrame();
2323
2324     m_policyDocumentLoader = loader;
2325 }
2326    
2327 DocumentLoader* FrameLoader::provisionalDocumentLoader()
2328 {
2329     return m_provisionalDocumentLoader.get();
2330 }
2331
2332 void FrameLoader::setProvisionalDocumentLoader(DocumentLoader* loader)
2333 {
2334     ASSERT(!loader || !m_provisionalDocumentLoader);
2335     ASSERT(!loader || loader->frameLoader() == this);
2336
2337     if (m_provisionalDocumentLoader && m_provisionalDocumentLoader != m_documentLoader)
2338         m_provisionalDocumentLoader->detachFromFrame();
2339
2340     m_provisionalDocumentLoader = loader;
2341 }
2342
2343 FrameState FrameLoader::state() const
2344 {
2345     return m_state;
2346 }
2347
2348 double FrameLoader::timeOfLastCompletedLoad()
2349 {
2350     return storedTimeOfLastCompletedLoad;
2351 }
2352
2353 void FrameLoader::setState(FrameState newState)
2354 {    
2355     m_state = newState;
2356     
2357     if (newState == FrameStateProvisional)
2358         provisionalLoadStarted();
2359     else if (newState == FrameStateComplete) {
2360         frameLoadCompleted();
2361         storedTimeOfLastCompletedLoad = currentTime();
2362         if (m_documentLoader)
2363             m_documentLoader->stopRecordingResponses();
2364     }
2365 }
2366
2367 void FrameLoader::clearProvisionalLoad()
2368 {
2369     setProvisionalDocumentLoader(0);
2370     if (Page* page = m_frame->page())
2371         page->progress()->progressCompleted(m_frame);
2372     setState(FrameStateComplete);
2373 }
2374
2375 void FrameLoader::markLoadComplete()
2376 {
2377     setState(FrameStateComplete);
2378 }
2379
2380 void FrameLoader::commitProvisionalLoad(PassRefPtr<CachedPage> prpCachedPage)
2381 {
2382     RefPtr<CachedPage> cachedPage = prpCachedPage;
2383     RefPtr<DocumentLoader> pdl = m_provisionalDocumentLoader;
2384     
2385     if (m_loadType != FrameLoadTypeReplace)
2386         closeOldDataSources();
2387     
2388     if (!cachedPage && !m_creatingInitialEmptyDocument)
2389         m_client->makeRepresentation(pdl.get());
2390     
2391     transitionToCommitted(cachedPage);
2392     
2393     // Call clientRedirectCancelledOrFinished() here so that the frame load delegate is notified that the redirect's
2394     // status has changed, if there was a redirect.  The frame load delegate may have saved some state about
2395     // the redirect in its -webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:.  Since we are
2396     // just about to commit a new page, there cannot possibly be a pending redirect at this point.
2397     if (m_sentRedirectNotification)
2398         clientRedirectCancelledOrFinished(false);
2399     
2400     if (cachedPage && cachedPage->document()) {
2401         open(*cachedPage);
2402         cachedPage->clear();
2403     } else {        
2404         KURL url = pdl->substituteData().responseURL();
2405         if (url.isEmpty())
2406             url = pdl->URL();
2407         if (url.isEmpty())
2408             url = pdl->responseURL();
2409         if (url.isEmpty())
2410             url = "about:blank";
2411
2412         didOpenURL(url);
2413     }
2414     opened();
2415 }
2416
2417 void FrameLoader::transitionToCommitted(PassRefPtr<CachedPage> cachedPage)
2418 {
2419     ASSERT(m_client->hasWebView());
2420     ASSERT(m_state == FrameStateProvisional);
2421
2422     if (m_state != FrameStateProvisional)
2423         return;
2424
2425     m_client->setCopiesOnScroll();
2426     updateHistoryForCommit();
2427
2428     // The call to closeURL() invokes the unload event handler, which can execute arbitrary
2429     // JavaScript. If the script initiates a new load, we need to abandon the current load,
2430     // or the two will stomp each other.
2431     DocumentLoader* pdl = m_provisionalDocumentLoader.get();
2432     if (m_documentLoader)
2433         closeURL();
2434     if (pdl != m_provisionalDocumentLoader)
2435         return;
2436
2437     // Nothing else can interupt this commit - set the Provisional->Committed transition in stone
2438     if (m_documentLoader)
2439         m_documentLoader->stopLoadingSubresources();
2440     if (m_documentLoader)
2441         m_documentLoader->stopLoadingPlugIns();
2442
2443     setDocumentLoader(m_provisionalDocumentLoader.get());
2444     setProvisionalDocumentLoader(0);
2445     setState(FrameStateCommittedPage);
2446
2447     // Handle adding the URL to the back/forward list.
2448     DocumentLoader* dl = m_documentLoader.get();
2449
2450     switch (m_loadType) {
2451         case FrameLoadTypeForward:
2452         case FrameLoadTypeBack:
2453         case FrameLoadTypeIndexedBackForward:
2454             if (Page* page = m_frame->page())
2455                 if (page->backForwardList()) {
2456                     updateHistoryForBackForwardNavigation();
2457
2458                     // Create a document view for this document, or used the cached view.
2459                     if (cachedPage)
2460                         m_client->setDocumentViewFromCachedPage(cachedPage.get());
2461                     else
2462                         m_client->makeDocumentView();
2463                 }
2464             break;
2465
2466         case FrameLoadTypeReload:
2467         case FrameLoadTypeSame:
2468         case FrameLoadTypeReplace:
2469             updateHistoryForReload();
2470             m_client->makeDocumentView();
2471             break;
2472
2473         // FIXME - just get rid of this case, and merge FrameLoadTypeReloadAllowingStaleData with the above case
2474         case FrameLoadTypeReloadAllowingStaleData:
2475             m_client->makeDocumentView();
2476             break;
2477
2478         case FrameLoadTypeStandard:
2479             updateHistoryForStandardLoad();
2480             m_client->makeDocumentView();
2481             break;
2482
2483         case FrameLoadTypeRedirectWithLockedHistory:
2484             updateHistoryForRedirectWithLockedHistory();
2485             m_client->makeDocumentView();
2486             break;
2487
2488         // FIXME Remove this check when dummy ds is removed (whatever "dummy ds" is).
2489         // An exception should be thrown if we're in the FrameLoadTypeUninitialized state.
2490         default:
2491             ASSERT_NOT_REACHED();
2492     }
2493
2494     m_responseMIMEType = dl->responseMIMEType();
2495
2496     // Tell the client we've committed this URL.
2497     ASSERT(m_client->hasFrameView());
2498
2499     if (m_creatingInitialEmptyDocument)
2500         return;
2501
2502     m_committedFirstRealDocumentLoad = true;
2503 }
2504
2505 bool FrameLoader::privateBrowsingEnabled() const
2506 {
2507     return m_client->privateBrowsingEnabled();
2508 }
2509
2510 void FrameLoader::clientRedirectCancelledOrFinished(bool cancelWithLoadInProgress)
2511 {
2512     // Note that -webView:didCancelClientRedirectForFrame: is called on the frame load delegate even if
2513     // the redirect succeeded.  We should either rename this API, or add a new method, like
2514     // -webView:didFinishClientRedirectForFrame:
2515     m_client->dispatchDidCancelClientRedirect();
2516
2517     if (!cancelWithLoadInProgress)
2518         m_quickRedirectComing = false;
2519
2520     m_sentRedirectNotification = false;
2521 }
2522
2523 void FrameLoader::clientRedirected(const KURL& URL, double seconds, double fireDate, bool lockHistory, bool isJavaScriptFormAction)
2524 {
2525     m_client->dispatchWillPerformClientRedirect(URL, seconds, fireDate);
2526     
2527     // Remember that we sent a redirect notification to the frame load delegate so that when we commit
2528     // the next provisional load, we can send a corresponding -webView:didCancelClientRedirectForFrame:
2529     m_sentRedirectNotification = true;
2530     
2531     // If a "quick" redirect comes in an, we set a special mode so we treat the next
2532     // load as part of the same navigation. If we don't have a document loader, we have
2533     // no "original" load on which to base a redirect, so we treat the redirect as a normal load.
2534     m_quickRedirectComing = lockHistory && m_documentLoader && !isJavaScriptFormAction;
2535 }
2536
2537 bool FrameLoader::shouldReload(const KURL& currentURL, const KURL& destinationURL)
2538 {
2539     // This function implements the rule: "Don't reload if navigating by fragment within
2540     // the same URL, but do reload if going to a new URL or to the same URL with no
2541     // fragment identifier at all."
2542     if (!currentURL.hasRef() && !destinationURL.hasRef())
2543         return true;
2544     return !equalIgnoringRef(currentURL, destinationURL);
2545 }
2546
2547 void FrameLoader::closeOldDataSources()
2548 {
2549     // FIXME: Is it important for this traversal to be postorder instead of preorder?
2550     // If so, add helpers for postorder traversal, and use them. If not, then lets not
2551     // use a recursive algorithm here.
2552     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
2553         child->loader()->closeOldDataSources();
2554     
2555     if (m_documentLoader)
2556         m_client->dispatchWillClose();
2557
2558     m_client->setMainFrameDocumentReady(false); // stop giving out the actual DOMDocument to observers
2559 }
2560
2561 void FrameLoader::open(CachedPage& cachedPage)
2562 {
2563     ASSERT(m_frame->page());
2564     ASSERT(m_frame->page()->mainFrame() == m_frame);
2565
2566     cancelRedirection();
2567
2568     // We still have to close the previous part page.
2569     closeURL();
2570
2571     m_isComplete = false;
2572     
2573     // Don't re-emit the load event.
2574     m_didCallImplicitClose = true;
2575     
2576     // Delete old status bar messages (if it _was_ activated on last URL).
2577     Settings* settings = m_frame->settings();
2578     if (settings && settings->isJavaScriptEnabled()) {
2579         m_frame->setJSStatusBarText(String());
2580         m_frame->setJSDefaultStatusBarText(String());
2581     }
2582
2583     KURL URL = cachedPage.URL();
2584
2585     if (URL.protocol().startsWith("http") && !URL.host().isEmpty() && URL.path().isEmpty())
2586         URL.setPath("/");
2587     
2588     m_URL = URL;
2589     m_workingURL = URL;
2590
2591     started();
2592
2593     clear();
2594
2595     Document* document = cachedPage.document();
2596     ASSERT(document);
2597     document->setInPageCache(false);
2598
2599     m_needsClear = true;
2600     m_shouldClearWindowProperties = true;
2601     m_isComplete = false;
2602     m_didCallImplicitClose = false;
2603     m_outgoingReferrer = URL.url();
2604
2605     FrameView* view = cachedPage.view();
2606     if (view)
2607         view->setWasScrolledByUser(false);
2608     m_frame->setView(view);
2609     
2610     m_frame->setDocument(document);
2611     m_decoder = document->decoder();
2612
2613     updatePolicyBaseURL();
2614
2615     cachedPage.restore(m_frame->page());
2616
2617     checkCompleted();
2618 }
2619
2620 bool FrameLoader::isStopping() const
2621 {
2622     return activeDocumentLoader()->isStopping();
2623 }
2624
2625 void FrameLoader::finishedLoading()
2626 {
2627     // Retain because the stop may release the last reference to it.
2628     RefPtr<Frame> protect(m_frame);
2629
2630     RefPtr<DocumentLoader> dl = activeDocumentLoader();
2631     dl->finishedLoading();
2632     if (!dl->mainDocumentError().isNull() || !dl->frameLoader())
2633         return;
2634     dl->setPrimaryLoadComplete(true);
2635     m_client->dispatchDidLoadMainResource(dl.get());
2636     checkLoadComplete();
2637 }
2638
2639 // FIXME: Which one of these URL methods is right?
2640
2641 KURL FrameLoader::url() const
2642 {
2643     return m_URL;
2644 }
2645
2646 KURL FrameLoader::URL() const
2647 {
2648     return activeDocumentLoader()->URL();
2649 }
2650
2651 bool FrameLoader::isArchiveLoadPending(ResourceLoader* loader) const
2652 {
2653     return m_client->isArchiveLoadPending(loader);
2654 }
2655
2656 bool FrameLoader::isHostedByObjectElement() const
2657 {
2658     HTMLFrameOwnerElement* owner = m_frame->ownerElement();
2659     return owner && owner->hasTagName(objectTag);
2660 }
2661
2662 bool FrameLoader::isLoadingMainFrame() const
2663 {
2664     Page* page = m_frame->page();
2665     return page && m_frame == page->mainFrame();
2666 }
2667
2668 bool FrameLoader::canShowMIMEType(const String& MIMEType) const
2669 {
2670     return m_client->canShowMIMEType(MIMEType);
2671 }
2672
2673 bool FrameLoader::representationExistsForURLScheme(const String& URLScheme)
2674 {
2675     return m_client->representationExistsForURLScheme(URLScheme);
2676 }
2677
2678 String FrameLoader::generatedMIMETypeForURLScheme(const String& URLScheme)
2679 {
2680     return m_client->generatedMIMETypeForURLScheme(URLScheme);
2681 }
2682
2683 void FrameLoader::cancelContentPolicyCheck()
2684 {
2685     m_client->cancelPolicyCheck();
2686     m_policyCheck.clear();
2687 }
2688
2689 void FrameLoader::didReceiveServerRedirectForProvisionalLoadForFrame()
2690 {
2691     m_client->dispatchDidReceiveServerRedirectForProvisionalLoad();
2692 }
2693
2694 void FrameLoader::finishedLoadingDocument(DocumentLoader* loader)
2695 {
2696     m_client->finishedLoading(loader);
2697 }
2698
2699 bool FrameLoader::isReplacing() const
2700 {
2701     return m_loadType == FrameLoadTypeReplace;
2702 }
2703
2704 void FrameLoader::setReplacing()
2705 {
2706     m_loadType = FrameLoadTypeReplace;
2707 }
2708
2709 void FrameLoader::revertToProvisional(DocumentLoader* loader)
2710 {
2711     m_client->revertToProvisionalState(loader);
2712 }
2713
2714 bool FrameLoader::subframeIsLoading() const
2715 {
2716     // It's most likely that the last added frame is the last to load so we walk backwards.
2717     for (Frame* child = m_frame->tree()->lastChild(); child; child = child->tree()->previousSibling()) {
2718         FrameLoader* childLoader = child->loader();
2719         DocumentLoader* documentLoader = childLoader->documentLoader();
2720         if (documentLoader && documentLoader->isLoadingInAPISense())
2721             return true;
2722         documentLoader = childLoader->provisionalDocumentLoader();
2723         if (documentLoader && documentLoader->isLoadingInAPISense())
2724             return true;
2725     }
2726     return false;
2727 }
2728
2729 void FrameLoader::willChangeTitle(DocumentLoader* loader)
2730 {
2731     m_client->willChangeTitle(loader);
2732 }
2733
2734 FrameLoadType FrameLoader::loadType() const
2735 {
2736     return m_loadType;
2737 }
2738
2739 void FrameLoader::stopPolicyCheck()
2740 {
2741     m_client->cancelPolicyCheck();
2742     PolicyCheck check = m_policyCheck;
2743     m_policyCheck.clear();
2744     check.cancel();
2745 }
2746
2747 void FrameLoader::checkLoadCompleteForThisFrame()
2748 {
2749     ASSERT(m_client->hasWebView());
2750
2751     switch (m_state) {
2752         case FrameStateProvisional: {
2753             if (m_delegateIsHandlingProvisionalLoadError)
2754                 return;
2755
2756             RefPtr<DocumentLoader> pdl = m_provisionalDocumentLoader;
2757             if (!pdl)
2758                 return;
2759                 
2760             // If we've received any errors we may be stuck in the provisional state and actually complete.
2761             const ResourceError& error = pdl->mainDocumentError();
2762             if (error.isNull())
2763                 return;
2764
2765             // Check all children first.
2766             RefPtr<HistoryItem> item;
2767             if (Page* page = m_frame->page())
2768                 if (isBackForwardLoadType(loadType()) && m_frame == page->mainFrame())
2769                     item = m_currentHistoryItem;
2770                 
2771             bool shouldReset = true;
2772             if (!pdl->isLoadingInAPISense()) {
2773                 m_delegateIsHandlingProvisionalLoadError = true;
2774                 m_client->dispatchDidFailProvisionalLoad(error);
2775                 m_delegateIsHandlingProvisionalLoadError = false;
2776
2777                 // FIXME: can stopping loading here possibly have any effect, if isLoading is false,
2778                 // which it must be to be in this branch of the if? And is it OK to just do a full-on
2779                 // stopAllLoaders instead of stopLoadingSubframes?
2780                 stopLoadingSubframes();
2781                 pdl->stopLoading();
2782
2783                 // Finish resetting the load state, but only if another load hasn't been started by the
2784                 // delegate callback.
2785                 if (pdl == m_provisionalDocumentLoader)
2786                     clearProvisionalLoad();
2787                 else if (m_provisionalDocumentLoader) {
2788                     KURL unreachableURL = m_provisionalDocumentLoader->unreachableURL();
2789                     if (!unreachableURL.isEmpty() && unreachableURL == pdl->request().url())
2790                         shouldReset = false;
2791                 }
2792             }
2793             if (shouldReset && item)
2794                 if (Page* page = m_frame->page())
2795                     page->backForwardList()->goToItem(item.get());
2796             return;
2797         }
2798         
2799         case FrameStateCommittedPage: {
2800             DocumentLoader* dl = m_documentLoader.get();            
2801             if (!dl || dl->isLoadingInAPISense())
2802                 return;
2803
2804             markLoadComplete();
2805
2806             // FIXME: Is this subsequent work important if we already navigated away?
2807             // Maybe there are bugs because of that, or extra work we can skip because
2808             // the new page is ready.
2809
2810             m_client->forceLayoutForNonHTML();
2811              
2812             // If the user had a scroll point, scroll to it, overriding the anchor point if any.
2813             if (Page* page = m_frame->page())
2814                 if ((isBackForwardLoadType(m_loadType) || m_loadType == FrameLoadTypeReload) && page->backForwardList())
2815                     restoreScrollPositionAndViewState();
2816
2817             if (m_creatingInitialEmptyDocument || !m_committedFirstRealDocumentLoad)
2818                 return;
2819
2820             const ResourceError& error = dl->mainDocumentError();
2821             if (!error.isNull())
2822                 m_client->dispatchDidFailLoad(error);
2823             else
2824                 m_client->dispatchDidFinishLoad();
2825
2826             if (Page* page = m_frame->page())
2827                 page->progress()->progressCompleted(m_frame);
2828             return;
2829         }
2830         
2831         case FrameStateComplete:
2832             // Even if already complete, we might have set a previous item on a frame that
2833             // didn't do any data loading on the past transaction. Make sure to clear these out.
2834             m_client->frameLoadCompleted();
2835             return;
2836     }
2837
2838     ASSERT_NOT_REACHED();
2839 }
2840
2841 void FrameLoader::continueAfterContentPolicy(PolicyAction policy)
2842 {
2843     PolicyCheck check = m_policyCheck;
2844     m_policyCheck.clear();
2845     check.call(policy);
2846 }
2847
2848 void FrameLoader::continueLoadAfterWillSubmitForm(PolicyAction)
2849 {
2850     if (!m_provisionalDocumentLoader)
2851         return;
2852
2853     m_provisionalDocumentLoader->prepareForLoadStart();
2854
2855     DocumentLoader* activeDocLoader = activeDocumentLoader();
2856     if (activeDocLoader && activeDocLoader->isLoadingMainResource())
2857         return;
2858
2859     m_provisionalDocumentLoader->setLoadingFromCachedPage(false);
2860
2861     unsigned long identifier = 0;
2862
2863     if (Page* page = m_frame->page()) {
2864         identifier = page->progress()->createUniqueIdentifier();
2865         dispatchAssignIdentifierToInitialRequest(identifier, m_provisionalDocumentLoader.get(), m_provisionalDocumentLoader->originalRequest());
2866     }
2867
2868     if (!m_provisionalDocumentLoader->startLoadingMainResource(identifier))
2869         m_provisionalDocumentLoader->updateLoading();
2870 }
2871
2872 void FrameLoader::didFirstLayout()
2873 {
2874     if (Page* page = m_frame->page())
2875         if (isBackForwardLoadType(m_loadType) && page->backForwardList())
2876             restoreScrollPositionAndViewState();
2877
2878     m_firstLayoutDone = true;
2879     m_client->dispatchDidFirstLayout();
2880 }
2881
2882 void FrameLoader::frameLoadCompleted()
2883 {
2884     m_client->frameLoadCompleted();
2885
2886     // After a canceled provisional load, firstLayoutDone is false.
2887     // Reset it to true if we're displaying a page.
2888     if (m_documentLoader)
2889         m_firstLayoutDone = true;
2890 }
2891
2892 bool FrameLoader::firstLayoutDone() const
2893 {
2894     return m_firstLayoutDone;
2895 }
2896
2897 bool FrameLoader::isQuickRedirectComing() const
2898 {
2899     return m_quickRedirectComing;
2900 }
2901
2902 void FrameLoader::detachChildren()
2903 {
2904     // FIXME: Is it really necessary to do this in reverse order?
2905     Frame* previous;
2906     for (Frame* child = m_frame->tree()->lastChild(); child; child = previous) {
2907         previous = child->tree()->previousSibling();
2908         child->loader()->detachFromParent();
2909     }
2910 }
2911
2912 void FrameLoader::recursiveCheckLoadComplete()
2913 {
2914     Vector<RefPtr<Frame>, 10> frames;
2915     
2916     for (RefPtr<Frame> frame = m_frame->tree()->firstChild(); frame; frame = frame->tree()->nextSibling())
2917         frames.append(frame);
2918     
2919     unsigned size = frames.size();
2920     for (unsigned i = 0; i < size; i++)
2921         frames[i]->loader()->recursiveCheckLoadComplete();
2922     
2923     checkLoadCompleteForThisFrame();
2924 }
2925
2926 // Called every time a resource is completely loaded, or an error is received.
2927 void FrameLoader::checkLoadComplete()
2928 {
2929     ASSERT(m_client->hasWebView());
2930     
2931     // FIXME: Always traversing the entire frame tree is a bit inefficient, but 
2932     // is currently needed in order to null out the previous history item for all frames.
2933     if (Page* page = m_frame->page())
2934         page->mainFrame()->loader()->recursiveCheckLoadComplete();
2935 }
2936
2937 int FrameLoader::numPendingOrLoadingRequests(bool recurse) const
2938 {
2939     if (!recurse)
2940         return numRequests(m_frame->document());
2941
2942     int count = 0;
2943     for (Frame* frame = m_frame; frame; frame = frame->tree()->traverseNext(m_frame))
2944         count += numRequests(frame->document());
2945     return count;
2946 }
2947
2948 FrameLoaderClient* FrameLoader::client() const
2949 {
2950     return m_client;
2951 }
2952
2953 void FrameLoader::submitForm(const FrameLoadRequest& request, Event* event)
2954 {
2955     // FIXME: We'd like to remove this altogether and fix the multiple form submission issue another way.
2956     // We do not want to submit more than one form from the same page,
2957     // nor do we want to submit a single form more than once.
2958     // This flag prevents these from happening; not sure how other browsers prevent this.
2959     // The flag is reset in each time we start handle a new mouse or key down event, and
2960     // also in setView since this part may get reused for a page from the back/forward cache.
2961     // The form multi-submit logic here is only needed when we are submitting a form that affects this frame.
2962     // FIXME: Frame targeting is only one of the ways the submission could end up doing something other
2963     // than replacing this frame's content, so this check is flawed. On the other hand, the check is hardly
2964     // needed any more now that we reset m_submittedFormURL on each mouse or key down event.
2965     Frame* target = m_frame->tree()->find(request.frameName());
2966     if (m_frame->tree()->isDescendantOf(target)) {
2967         if (m_submittedFormURL == request.resourceRequest().url())
2968             return;
2969         m_submittedFormURL = request.resourceRequest().url();
2970     }
2971
2972     // FIXME: We should probably call userGestureHint() to tell whether this form submission was the result of a user gesture.
2973     load(request, false, true, event, m_formAboutToBeSubmitted.get(), m_formValuesAboutToBeSubmitted);
2974
2975     clearRecordedFormValues();
2976 }
2977
2978 void FrameLoader::urlSelected(const FrameLoadRequest& request, Event* event, bool lockHistory, bool userGesture)
2979 {
2980     FrameLoadRequest copy = request;
2981     if (copy.resourceRequest().httpReferrer().isEmpty())
2982         copy.resourceRequest().setHTTPReferrer(m_outgoingReferrer);
2983
2984     load(copy, lockHistory, userGesture, event, 0, HashMap<String, String>());
2985 }
2986     
2987 String FrameLoader::userAgent(const KURL& url) const
2988 {
2989     return m_client->userAgent(url);
2990 }
2991
2992 void FrameLoader::tokenizerProcessedData()
2993 {
2994     ASSERT(m_frame->page());
2995     ASSERT(m_frame->document());
2996
2997     checkCompleted();
2998 }
2999
3000 void FrameLoader::didTellBridgeAboutLoad(const String& URL)
3001 {
3002     m_urlsBridgeKnowsAbout.add(URL);
3003 }
3004
3005 bool FrameLoader::haveToldBridgeAboutLoad(const String& URL)
3006 {
3007     return m_urlsBridgeKnowsAbout.contains(URL);
3008 }
3009
3010 void FrameLoader::handledOnloadEvents()
3011 {
3012     m_client->dispatchDidHandleOnloadEvents();
3013 }
3014
3015 void FrameLoader::frameDetached()
3016 {
3017     stopAllLoaders();
3018     detachFromParent();
3019 }
3020
3021 void FrameLoader::detachFromParent()
3022 {
3023     RefPtr<Frame> protect(m_frame);
3024
3025     closeURL();
3026     stopAllLoaders();
3027     saveScrollPositionAndViewStateToItem(currentHistoryItem());
3028     detachChildren();
3029
3030     if (Page* page = m_frame->page())
3031         page->inspectorController()->frameDetachedFromParent(m_frame);
3032
3033     m_client->detachedFromParent2();
3034     setDocumentLoader(0);
3035     m_client->detachedFromParent3();
3036     if (Frame* parent = m_frame->tree()->parent()) {
3037         parent->tree()->removeChild(m_frame);
3038         parent->loader()->scheduleCheckCompleted();
3039     } else {
3040         m_frame->setView(0);
3041         m_frame->pageDestroyed();
3042     }
3043 #if PLATFORM(MAC)
3044     [m_frame->bridge() close];
3045 #endif
3046     m_client->detachedFromParent4();
3047 }
3048
3049 void FrameLoader::dispatchDidChangeLocationWithinPage()
3050 {
3051     m_client->dispatchDidChangeLocationWithinPage();
3052 }
3053
3054 void FrameLoader::dispatchDidFinishLoadToClient()
3055 {
3056     m_client->didFinishLoad();
3057 }
3058
3059 void FrameLoader::updateGlobalHistoryForStandardLoad(const KURL& url)
3060 {
3061     m_client->updateGlobalHistoryForStandardLoad(url);
3062 }
3063
3064 void FrameLoader::updateGlobalHistoryForReload(const KURL& url)
3065 {
3066     m_client->updateGlobalHistoryForReload(url);
3067 }
3068
3069 bool FrameLoader::shouldGoToHistoryItem(HistoryItem* item) const
3070 {
3071     return m_client->shouldGoToHistoryItem(item);
3072 }
3073
3074 void FrameLoader::addExtraFieldsToRequest(ResourceRequest& request, bool mainResource, bool alwaysFromRequest)
3075 {
3076     applyUserAgent(request);
3077     
3078     if (m_loadType == FrameLoadTypeReload)
3079         request.setHTTPHeaderField("Cache-Control", "max-age=0");
3080     
3081     // Don't set the cookie policy URL if it's already been set.
3082     if (request.mainDocumentURL().isEmpty()) {
3083         if (mainResource && (isLoadingMainFrame() || alwaysFromRequest))
3084             request.setMainDocumentURL(request.url());
3085         else if (Page* page = m_frame->page())
3086             request.setMainDocumentURL(page->mainFrame()->loader()->url());
3087     }
3088     
3089     if (mainResource)
3090         request.setHTTPAccept("text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5");
3091 }
3092
3093 void FrameLoader::committedLoad(DocumentLoader* loader, const char* data, int length)
3094 {
3095     m_client->committedLoad(loader, data, length);
3096 }
3097
3098 void FrameLoader::post(const KURL& URL, const String& referrer, const String& frameName, PassRefPtr<FormData> formData, 
3099     const String& contentType, Event* event, HTMLFormElement* form, const HashMap<String, String>& formValues)
3100 {
3101     // When posting, use the NSURLRequestReloadIgnoringCacheData load flag.
3102     // This prevents a potential bug which may cause a page with a form that uses itself
3103     // as an action to be returned from the cache without submitting.
3104
3105     // FIXME: Where's the code that implements what the comment above says?
3106
3107     ResourceRequest request(URL);
3108     addExtraFieldsToRequest(request, true, true);
3109
3110     if (!referrer.isEmpty())
3111         request.setHTTPReferrer(referrer);
3112     request.setHTTPMethod("POST");
3113     request.setHTTPBody(formData);
3114     request.setHTTPContentType(contentType);
3115
3116     NavigationAction action(URL, FrameLoadTypeStandard, true, event);
3117
3118     RefPtr<FormState> formState;
3119     if (form && !formValues.isEmpty())
3120         formState = FormState::create(form, formValues, m_frame);
3121
3122     if (!frameName.isEmpty()) {
3123         if (Frame* targetFrame = m_frame->tree()->find(frameName))
3124             targetFrame->loader()->load(request, action, FrameLoadTypeStandard, formState.release());
3125         else
3126             checkNewWindowPolicy(action, request, formState.release(), frameName);
3127     } else
3128         load(request, action, FrameLoadTypeStandard, formState.release());
3129 }
3130
3131 bool FrameLoader::isReloading() const
3132 {
3133     return documentLoader()->request().cachePolicy() == ReloadIgnoringCacheData;
3134 }
3135
3136 void FrameLoader::loadEmptyDocumentSynchronously()
3137 {
3138     ResourceRequest request(KURL(""));
3139     load(request);
3140 }
3141
3142 void FrameLoader::loadResourceSynchronously(const ResourceRequest& request, ResourceError& error, ResourceResponse& response, Vector<char>& data)
3143 {
3144     // Since this is a subresource, we can load any URL (we ignore the return value).
3145     // But we still want to know whether we should hide the referrer or not, so we call the canLoad method.
3146     String referrer = m_outgoingReferrer;
3147     if (shouldHideReferrer(request.url(), referrer))
3148         referrer = String();
3149     
3150     ResourceRequest initialRequest = request;
3151     initialRequest.setTimeoutInterval(10);
3152     
3153     if (initialRequest.isConditional())
3154         initialRequest.setCachePolicy(ReloadIgnoringCacheData);
3155     else
3156         initialRequest.setCachePolicy(documentLoader()->request().cachePolicy());
3157     
3158     if (!referrer.isEmpty())
3159         initialRequest.setHTTPReferrer(referrer);
3160
3161     if (Page* page = m_frame->page())
3162         initialRequest.setMainDocumentURL(page->mainFrame()->loader()->documentLoader()->request().url());
3163     initialRequest.setHTTPUserAgent(client()->userAgent(request.url()));
3164
3165     unsigned long identifier = 0;    
3166     ResourceRequest newRequest(initialRequest);
3167     requestFromDelegate(newRequest, identifier, error);
3168
3169     if (error.isNull()) {
3170         ASSERT(!newRequest.isNull());
3171         didTellBridgeAboutLoad(newRequest.url().url());
3172         ResourceHandle::loadResourceSynchronously(newRequest, error, response, data);
3173     }
3174     
3175     sendRemainingDelegateMessages(identifier, response, data.size(), error);
3176 }
3177
3178 void FrameLoader::assignIdentifierToInitialRequest(unsigned long identifier, const ResourceRequest& clientRequest)
3179 {
3180     return dispatchAssignIdentifierToInitialRequest(identifier, activeDocumentLoader(), clientRequest);
3181 }
3182
3183 void FrameLoader::willSendRequest(ResourceLoader* loader, ResourceRequest& clientRequest, const ResourceResponse& redirectResponse)
3184 {
3185     applyUserAgent(clientRequest);
3186     dispatchWillSendRequest(loader->documentLoader(), loader->identifier(), clientRequest, redirectResponse);
3187 }
3188
3189 void FrameLoader::didReceiveResponse(ResourceLoader* loader, const ResourceResponse& r)
3190 {
3191     activeDocumentLoader()->addResponse(r);
3192     
3193     if (Page* page = m_frame->page())
3194         page->progress()->incrementProgress(loader->identifier(), r);
3195     dispatchDidReceiveResponse(loader->documentLoader(), loader->identifier(), r);
3196 }
3197
3198 void FrameLoader::didReceiveData(ResourceLoader* loader, const char* data, int length, int lengthReceived)
3199 {
3200     if (Page* page = m_frame->page())
3201         page->progress()->incrementProgress(loader->identifier(), data, length);
3202     dispatchDidReceiveContentLength(loader->documentLoader(), loader->identifier(), lengthReceived);
3203 }
3204
3205 void FrameLoader::didFailToLoad(ResourceLoader* loader, const ResourceError& error)
3206 {
3207     if (Page* page = m_frame->page())
3208         page->progress()->completeProgress(loader->identifier());
3209     if (!error.isNull())
3210         m_client->dispatchDidFailLoading(loader->documentLoader(), loader->identifier(), error);
3211 }
3212
3213 const ResourceRequest& FrameLoader::originalRequest() const
3214 {
3215     return activeDocumentLoader()->originalRequestCopy();
3216 }
3217
3218 void FrameLoader::receivedMainResourceError(const ResourceError& error, bool isComplete)
3219 {
3220     // Retain because the stop may release the last reference to it.
3221     RefPtr<Frame> protect(m_frame);
3222
3223     RefPtr<DocumentLoader> loader = activeDocumentLoader();
3224     
3225     if (isComplete) {
3226         // FIXME: Don't want to do this if an entirely new load is going, so should check
3227         // that both data sources on the frame are either this or nil.
3228         stop();
3229         if (m_client->shouldFallBack(error))
3230             handleFallbackContent();
3231     }
3232     
3233     if (m_state == FrameStateProvisional) {
3234         KURL failedURL = m_provisionalDocumentLoader->originalRequestCopy().url();
3235         didNotOpenURL(failedURL);
3236             
3237         // We might have made a page cache item, but now we're bailing out due to an error before we ever
3238         // transitioned to the new page (before WebFrameState == commit).  The goal here is to restore any state
3239         // so that the existing view (that wenever got far enough to replace) can continue being used.
3240         m_frame->document()->setInPageCache(false);
3241         invalidateCurrentItemCachedPage();
3242         
3243         // Call clientRedirectCancelledOrFinished here so that the frame load delegate is notified that the redirect's
3244         // status has changed, if there was a redirect. The frame load delegate may have saved some state about
3245         // the redirect in its -webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:. Since we are definitely
3246         // not going to use this provisional resource, as it was cancelled, notify the frame load delegate that the redirect
3247         // has ended.
3248         if (m_sentRedirectNotification)
3249             clientRedirectCancelledOrFinished(false);
3250     }
3251     
3252     
3253     loader->mainReceivedError(error, isComplete);
3254 }
3255
3256 void FrameLoader::callContinueFragmentScrollAfterNavigationPolicy(void* argument,
3257     const ResourceRequest& request, PassRefPtr<FormState>, bool shouldContinue)
3258 {
3259     FrameLoader* loader = static_cast<FrameLoader*>(argument);
3260     loader->continueFragmentScrollAfterNavigationPolicy(request, shouldContinue);
3261 }
3262
3263 void FrameLoader::continueFragmentScrollAfterNavigationPolicy(const ResourceRequest& request, bool shouldContinue)
3264 {
3265     bool isRedirect = m_quickRedirectComing;
3266     m_quickRedirectComing = false;
3267
3268     if (!shouldContinue)
3269         return;
3270
3271     KURL URL = request.url();
3272     
3273     m_documentLoader->replaceRequestURLForAnchorScroll(URL);
3274     if (!isRedirect && !shouldTreatURLAsSameAsCurrent(URL)) {
3275         // NB: must happen after _setURL, since we add based on the current request.
3276         // Must also happen before we openURL and displace the scroll position, since
3277         // adding the BF item will save away scroll state.
3278         
3279         // NB2:  If we were loading a long, slow doc, and the user anchor nav'ed before
3280         // it was done, currItem is now set the that slow doc, and prevItem is whatever was
3281         // before it.  Adding the b/f item will bump the slow doc down to prevItem, even
3282         // though its load is not yet done.  I think this all works out OK, for one because
3283         // we have already saved away the scroll and doc state for the long slow load,
3284         // but it's not an obvious case.
3285
3286         addHistoryItemForFragmentScroll();
3287     }
3288     
3289     scrollToAnchor(URL);
3290     
3291     if (!isRedirect)
3292         // This will clear previousItem from the rest of the frame tree that didn't
3293         // doing any loading. We need to make a pass on this now, since for anchor nav
3294         // we'll not go through a real load and reach Completed state.
3295         checkLoadComplete();
3296  
3297     dispatchDidChangeLocationWithinPage();
3298     m_client->didFinishLoad();
3299 }
3300
3301 void FrameLoader::opened()
3302 {
3303     if (m_loadType == FrameLoadTypeStandard && m_documentLoader->isClientRedirect())
3304         updateHistoryForClientRedirect();
3305
3306     if (m_documentLoader->isLoadingFromCachedPage()) {
3307         m_frame->document()->didRestoreFromCache();
3308         
3309         // Force a layout to update view size and thereby update scrollbars.
3310         m_client->forceLayout();
3311
3312         const ResponseVector& responses = m_documentLoader->responses();
3313         size_t count = responses.size();
3314         for (size_t i = 0; i < count; i++) {
3315             const ResourceResponse& response = responses[i];
3316             // FIXME: If the WebKit client changes or cancels the request, this is not respected.
3317             ResourceError error;
3318             unsigned long identifier;
3319             ResourceRequest request(response.url());
3320             requestFromDelegate(request, identifier, error);
3321             // FIXME: If we get a resource with more than 2B bytes, this code won't do the right thing.
3322             // However, with today's computers and networking speeds, this won't happen in practice.
3323             // Could be an issue with a giant local file.
3324             sendRemainingDelegateMessages(identifier, response, static_cast<int>(response.expectedContentLength()), error);
3325         }
3326         
3327         pageCache()->remove(m_currentHistoryItem.get());
3328
3329         m_documentLoader->setPrimaryLoadComplete(true);
3330
3331         // FIXME: Why only this frame and not parent frames?
3332         checkLoadCompleteForThisFrame();
3333     }
3334 }
3335
3336 void FrameLoader::checkNewWindowPolicy(const NavigationAction& action, const ResourceRequest& request,
3337     PassRefPtr<FormState> formState, const String& frameName)
3338 {
3339     m_policyCheck.set(request, formState, frameName,
3340         callContinueLoadAfterNewWindowPolicy, this);
3341     m_client->dispatchDecidePolicyForNewWindowAction(&FrameLoader::continueAfterNewWindowPolicy,
3342         action, request, frameName);
3343 }
3344
3345 void FrameLoader::continueAfterNewWindowPolicy(PolicyAction policy)
3346 {
3347     PolicyCheck check = m_policyCheck;
3348     m_policyCheck.clear();
3349
3350     switch (policy) {
3351         case PolicyIgnore:
3352             check.clearRequest();
3353             break;
3354         case PolicyDownload:
3355             m_client->startDownload(check.request());
3356             check.clearRequest();
3357             break;
3358         case PolicyUse:
3359             break;
3360     }
3361
3362     check.call(policy == PolicyUse);
3363 }
3364
3365 void FrameLoader::checkNavigationPolicy(const ResourceRequest& request, DocumentLoader* loader,
3366     PassRefPtr<FormState> formState, NavigationPolicyDecisionFunction function, void* argument)
3367 {
3368     NavigationAction action = loader->triggeringAction();
3369     if (action.isEmpty()) {
3370         action = NavigationAction(request.url(), NavigationTypeOther);
3371         loader->setTriggeringAction(action);
3372     }
3373         
3374     // Don't ask more than once for the same request or if we are loading an empty URL.
3375     // This avoids confusion on the part of the client.
3376     if (equalIgnoringHeaderFields(request, loader->lastCheckedRequest()) || (!request.isNull() && request.url().isEmpty())) {
3377         function(argument, request, 0, true);
3378         loader->setLastCheckedRequest(request);
3379         return;
3380     }
3381     
3382     // We are always willing to show alternate content for unreachable URLs;
3383     // treat it like a reload so it maintains the right state for b/f list.
3384     if (loader->substituteData().isValid() && !loader->substituteData().failingURL().isEmpty()) {
3385         if (isBackForwardLoadType(m_policyLoadType))
3386             m_policyLoadType = FrameLoadTypeReload;
3387         function(argument, request, 0, true);
3388         return;
3389     }
3390     
3391     loader->setLastCheckedRequest(request);
3392
3393     m_policyCheck.set(request, formState, function, argument);
3394
3395     m_delegateIsDecidingNavigationPolicy = true;
3396     m_client->dispatchDecidePolicyForNavigationAction(&FrameLoader::continueAfterNavigationPolicy,
3397         action, request);
3398     m_delegateIsDecidingNavigationPolicy = false;
3399 }
3400
3401 void FrameLoader::continueAfterNavigationPolicy(PolicyAction policy)
3402 {
3403     PolicyCheck check = m_policyCheck;
3404     m_policyCheck.clear();
3405
3406     bool shouldContinue = policy == PolicyUse;
3407     
3408     switch (policy) {
3409         case PolicyIgnore:
3410             check.clearRequest();
3411             break;
3412         case PolicyDownload:
3413             m_client->startDownload(check.request());
3414             check.clearRequest();
3415             break;
3416         case PolicyUse: {
3417             ResourceRequest request(check.request());
3418             
3419             if (!m_client->canHandleRequest(request)) {
3420                 handleUnimplementablePolicy(m_client->cannotShowURLError(check.request()));
3421                 check.clearRequest();
3422                 shouldContinue = false;
3423             }
3424             break;
3425         }
3426     }
3427
3428     check.call(shouldContinue);
3429 }
3430
3431 void FrameLoader::callContinueLoadAfterNavigationPolicy(void* argument,
3432     const ResourceRequest& request, PassRefPtr<FormState> formState, bool shouldContinue)
3433 {
3434     FrameLoader* loader = static_cast<FrameLoader*>(argument);
3435     loader->continueLoadAfterNavigationPolicy(request, formState, shouldContinue);
3436 }
3437
3438 void FrameLoader::continueLoadAfterNavigationPolicy(const ResourceRequest& request, PassRefPtr<FormState> formState, bool shouldContinue)
3439 {
3440     // If we loaded an alternate page to replace an unreachableURL, we'll get in here with a
3441     // nil policyDataSource because loading the alternate page will have passed
3442     // through this method already, nested; otherwise, policyDataSource should still be set.
3443     ASSERT(m_policyDocumentLoader || !m_provisionalDocumentLoader->unreachableURL().isEmpty());
3444
3445     bool isTargetItem = m_provisionalHistoryItem ? m_provisionalHistoryItem->isTargetItem() : false;
3446
3447     // Two reasons we can't continue:
3448     //    1) Navigation policy delegate said we can't so request is nil. A primary case of this 
3449     //       is the user responding Cancel to the form repost nag sheet.
3450     //    2) User responded Cancel to an alert popped up by the before unload event handler.
3451     // The "before unload" event handler runs only for the main frame.
3452     bool canContinue = shouldContinue && (!isLoadingMainFrame() || m_frame->shouldClose());
3453
3454     if (!canContinue) {
3455         // If we were waiting for a quick redirect, but the policy delegate decided to ignore it, then we 
3456         // need to report that the client redirect was cancelled.
3457         if (m_quickRedirectComing)
3458             clientRedirectCancelledOrFinished(false);
3459
3460         setPolicyDocumentLoader(0);
3461
3462         // If the navigation request came from the back/forward menu, and we punt on it, we have the 
3463         // problem that we have optimistically moved the b/f cursor already, so move it back.  For sanity, 
3464         // we only do this when punting a navigation for the target frame or top-level frame.  
3465         if ((isTargetItem || isLoadingMainFrame()) && isBackForwardLoadType(m_policyLoadType))
3466             if (Page* page = m_frame->page()) {
3467                 Frame* mainFrame = page->mainFrame();
3468                 if (HistoryItem* resetItem = mainFrame->loader()->m_currentHistoryItem.get())
3469                     page->backForwardList()->goToItem(resetItem);
3470             }
3471         return;
3472     }
3473
3474     FrameLoadType type = m_policyLoadType;
3475     stopAllLoaders();
3476     setProvisionalDocumentLoader(m_policyDocumentLoader.get());
3477     m_loadType = type;
3478     setState(FrameStateProvisional);
3479
3480     setPolicyDocumentLoader(0);
3481
3482     if (isBackForwardLoadType(type) && loadProvisionalItemFromCachedPage())
3483         return;
3484
3485     if (formState)
3486         m_client->dispatchWillSubmitForm(&FrameLoader::continueLoadAfterWillSubmitForm, formState);
3487     else
3488         continueLoadAfterWillSubmitForm();
3489 }
3490
3491
3492 void FrameLoader::callContinueLoadAfterNewWindowPolicy(void* argument,
3493     const ResourceRequest& request, PassRefPtr<FormState> formState, const String& frameName, bool shouldContinue)
3494 {
3495     FrameLoader* loader = static_cast<FrameLoader*>(argument);
3496     loader->continueLoadAfterNewWindowPolicy(request, formState, frameName, shouldContinue);
3497 }
3498
3499 void FrameLoader::continueLoadAfterNewWindowPolicy(const ResourceRequest& request,
3500     PassRefPtr<FormState> formState, const String& frameName, bool shouldContinue)
3501 {
3502     if (!shouldContinue)
3503         return;
3504
3505     RefPtr<Frame> frame = m_frame;
3506     RefPtr<Frame> mainFrame = m_client->dispatchCreatePage();
3507     if (!mainFrame)
3508         return;
3509
3510     if (frameName != "_blank")
3511         mainFrame->tree()->setName(frameName);
3512
3513     mainFrame->loader()->setOpenedByDOM();
3514     mainFrame->loader()->m_client->dispatchShow();
3515     mainFrame->loader()->setOpener(frame.get());
3516     mainFrame->loader()->load(request, NavigationAction(), FrameLoadTypeStandard, formState);
3517 }
3518
3519 void FrameLoader::sendRemainingDelegateMessages(unsigned long identifier, const ResourceResponse& response, int length, const ResourceError& error)
3520 {    
3521     if (!response.isNull())
3522         dispatchDidReceiveResponse(m_documentLoader.get(), identifier, response);
3523     
3524     if (length > 0)
3525         dispatchDidReceiveContentLength(m_documentLoader.get(), identifier, length);
3526     
3527     if (error.isNull())
3528         dispatchDidFinishLoading(m_documentLoader.get(), identifier);
3529     else
3530         m_client->dispatchDidFailLoading(m_documentLoader.get(), identifier, error);
3531 }
3532
3533 void FrameLoader::requestFromDelegate(ResourceRequest& request, unsigned long& identifier, ResourceError& error)
3534 {
3535     ASSERT(!request.isNull());
3536
3537     identifier = 0;
3538     if (Page* page = m_frame->page()) {
3539         identifier = page->progress()->createUniqueIdentifier();
3540         dispatchAssignIdentifierToInitialRequest(identifier, m_documentLoader.get(), request);
3541     }
3542
3543     ResourceRequest newRequest(request);
3544     dispatchWillSendRequest(m_documentLoader.get(), identifier, newRequest, ResourceResponse());
3545
3546     if (newRequest.isNull())
3547         error = m_client->cancelledError(request);
3548     else
3549         error = ResourceError();
3550
3551     request = newRequest;
3552 }
3553
3554 void FrameLoader::loadedResourceFromMemoryCache(const ResourceRequest& request, const ResourceResponse& response, int length)
3555 {
3556     if (dispatchDidLoadResourceFromMemoryCache(m_documentLoader.get(), request, response, length))
3557         return;
3558
3559     unsigned long identifier;
3560     ResourceError error;
3561     ResourceRequest r(request);
3562     requestFromDelegate(r, identifier, error);
3563     sendRemainingDelegateMessages(identifier, response, length, error);
3564 }
3565
3566 void FrameLoader::applyUserAgent(ResourceRequest& request)
3567 {
3568     String userAgent = client()->userAgent(request.url());
3569     ASSERT(!userAgent.isNull());
3570     request.setHTTPUserAgent(userAgent);
3571 }
3572
3573 bool FrameLoader::canGoBackOrForward(int distance) const
3574 {
3575     if (Page* page = m_frame->page()) {
3576         if (distance == 0)
3577             return true;
3578         if (distance > 0 && distance <= page->backForwardList()->forwardListCount())
3579             return true;
3580         if (distance < 0 && -distance <= page->backForwardList()->backListCount())
3581             return true;
3582     }
3583     return false;
3584 }
3585
3586 int FrameLoader::getHistoryLength()
3587 {
3588     if (Page* page = m_frame->page())
3589         return page->backForwardList()->backListCount() + 1;
3590     return 0;
3591 }
3592
3593 KURL FrameLoader::historyURL(int distance)
3594 {
3595     if (Page* page = m_frame->page()) {
3596         BackForwardList* list = page->backForwardList();
3597         HistoryItem* item = list->itemAtIndex(distance);
3598         if (!item) {
3599             if (distance > 0) {
3600                 int forwardListCount = list->forwardListCount();
3601                 if (forwardListCount > 0)
3602                     item = list->itemAtIndex(forwardListCount);
3603             } else {
3604                 int backListCount = list->backListCount();
3605                 if (backListCount > 0)
3606                     item = list->itemAtIndex(-backListCount);
3607             }
3608         }
3609         if (item)
3610             return item->url();
3611     }
3612     return KURL();
3613 }
3614
3615 void FrameLoader::addHistoryItemForFragmentScroll()
3616 {
3617     addBackForwardItemClippedAtTarget(false);
3618 }
3619
3620 bool FrameLoader::loadProvisionalItemFromCachedPage()
3621 {
3622     RefPtr<CachedPage> cachedPage = pageCache()->get(m_provisionalHistoryItem.get());
3623     if (!cachedPage || !cachedPage->document())
3624         return false;
3625     provisionalDocumentLoader()->loadFromCachedPage(cachedPage.release());
3626     return true;
3627 }
3628
3629 void FrameLoader::cachePageForHistoryItem(HistoryItem* item)
3630 {
3631     if (Page* page = m_frame->page()) {
3632         RefPtr<CachedPage> cachedPage = CachedPage::create(page);
3633         cachedPage->setTimeStampToNow();
3634         cachedPage->setDocumentLoader(documentLoader());
3635         m_client->saveDocumentViewToCachedPage(cachedPage.get());
3636
3637         pageCache()->add(item, cachedPage.release());
3638     }
3639 }
3640
3641 bool FrameLoader::shouldTreatURLAsSameAsCurrent(const KURL& URL) const