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