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