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