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