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