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