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