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