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