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