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