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