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