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