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()->isLoading()
1482         && !documentLoader()->isStopping()) {
1483         
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     }
1492 }
1493
1494 bool FrameLoader::userGestureHint()
1495 {
1496     Frame* rootFrame = m_frame;
1497     while (rootFrame->tree()->parent())
1498         rootFrame = rootFrame->tree()->parent();
1499
1500     if (rootFrame->scriptProxy())
1501         return rootFrame->scriptProxy()->interpreter()->wasRunByUserGesture();
1502
1503     return true; // If JavaScript is disabled, a user gesture must have initiated the navigation
1504 }
1505
1506 void FrameLoader::didNotOpenURL(const KURL& URL)
1507 {
1508     if (m_submittedFormURL == URL)
1509         m_submittedFormURL = KURL();
1510 }
1511
1512 void FrameLoader::resetMultipleFormSubmissionProtection()
1513 {
1514     m_submittedFormURL = KURL();
1515 }
1516
1517 void FrameLoader::setEncoding(const String& name, bool userChosen)
1518 {
1519     if (!m_workingURL.isEmpty())
1520         receivedFirstData();
1521     m_encoding = name;
1522     m_encodingWasChosenByUser = userChosen;
1523 }
1524
1525 void FrameLoader::addData(const char* bytes, int length)
1526 {
1527     ASSERT(m_workingURL.isEmpty());
1528     ASSERT(m_frame->document());
1529     ASSERT(m_frame->document()->parsing());
1530     write(bytes, length);
1531 }
1532
1533 bool FrameLoader::canCachePage()
1534 {
1535     if (!m_client->canCachePage())
1536         return false;
1537         
1538     return m_frame->document()
1539         && !m_frame->tree()->childCount()
1540         && !m_frame->tree()->parent()
1541         && !m_containsPlugIns
1542         && !m_URL.protocol().startsWith("https")
1543         && !m_frame->document()->applets()->length()
1544         && !m_frame->document()->hasWindowEventListener(unloadEvent)
1545         && !m_frame->document()->hasPasswordField();
1546 }
1547
1548 void FrameLoader::updatePolicyBaseURL()
1549 {
1550     if (m_frame->tree()->parent() && m_frame->tree()->parent()->document())
1551         setPolicyBaseURL(m_frame->tree()->parent()->document()->policyBaseURL());
1552     else
1553         setPolicyBaseURL(m_URL.url());
1554 }
1555
1556 void FrameLoader::setPolicyBaseURL(const String& s)
1557 {
1558     if (m_frame->document())
1559         m_frame->document()->setPolicyBaseURL(s);
1560     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
1561         child->loader()->setPolicyBaseURL(s);
1562 }
1563
1564 // This does the same kind of work that FrameLoader::openURL does, except it relies on the fact
1565 // that a higher level already checked that the URLs match and the scrolling is the right thing to do.
1566 void FrameLoader::scrollToAnchor(const KURL& URL)
1567 {
1568     m_URL = URL;
1569     started();
1570
1571     gotoAnchor();
1572
1573     // It's important to model this as a load that starts and immediately finishes.
1574     // Otherwise, the parent frame may think we never finished loading.
1575     m_isComplete = false;
1576     checkCompleted();
1577 }
1578
1579 bool FrameLoader::isComplete() const
1580 {
1581     return m_isComplete;
1582 }
1583
1584 bool FrameLoader::isLoadingMainResource() const
1585 {
1586     return m_isLoadingMainResource;
1587 }
1588
1589 KURL FrameLoader::url() const
1590 {
1591     return m_URL;
1592 }
1593
1594 void FrameLoader::scheduleRedirection(ScheduledRedirection* redirection)
1595 {
1596     stopRedirectionTimer();
1597     m_scheduledRedirection.set(redirection);
1598     if (m_isComplete)
1599         startRedirectionTimer();
1600 }
1601
1602 void FrameLoader::startRedirectionTimer()
1603 {
1604     ASSERT(m_scheduledRedirection);
1605
1606     m_redirectionTimer.stop();
1607     m_redirectionTimer.startOneShot(m_scheduledRedirection->delay);
1608
1609     switch (m_scheduledRedirection->type) {
1610         case ScheduledRedirection::redirection:
1611         case ScheduledRedirection::locationChange:
1612         case ScheduledRedirection::locationChangeDuringLoad:
1613             clientRedirected(m_scheduledRedirection->URL.deprecatedString(),
1614                 m_scheduledRedirection->delay,
1615                 currentTime() + m_redirectionTimer.nextFireInterval(),
1616                 m_scheduledRedirection->lockHistory,
1617                 m_isExecutingJavaScriptFormAction);
1618             return;
1619         case ScheduledRedirection::historyNavigation:
1620             // Don't report history navigations.
1621             return;
1622     }
1623     ASSERT_NOT_REACHED();
1624 }
1625
1626 void FrameLoader::stopRedirectionTimer()
1627 {
1628     if (!m_redirectionTimer.isActive())
1629         return;
1630
1631     m_redirectionTimer.stop();
1632
1633     if (m_scheduledRedirection) {
1634         switch (m_scheduledRedirection->type) {
1635             case ScheduledRedirection::redirection:
1636             case ScheduledRedirection::locationChange:
1637             case ScheduledRedirection::locationChangeDuringLoad:
1638                 clientRedirectCancelledOrFinished(m_cancellingWithLoadInProgress);
1639                 return;
1640             case ScheduledRedirection::historyNavigation:
1641                 // Don't report history navigations.
1642                 return;
1643         }
1644         ASSERT_NOT_REACHED();
1645     }
1646 }
1647
1648 void FrameLoader::updateBaseURLForEmptyDocument()
1649 {
1650     HTMLFrameOwnerElement* owner = m_frame->ownerElement();
1651     // FIXME: Should embed be included?
1652     if (owner && (owner->hasTagName(iframeTag) || owner->hasTagName(objectTag) || owner->hasTagName(embedTag)))
1653         m_frame->document()->setBaseURL(m_frame->tree()->parent()->document()->baseURL());
1654 }
1655
1656 void FrameLoader::completed()
1657 {
1658     RefPtr<Frame> protect(m_frame);
1659     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
1660         child->loader()->parentCompleted();
1661     if (Frame* parent = m_frame->tree()->parent())
1662         parent->loader()->checkCompleted();
1663     submitFormAgain();
1664 }
1665
1666 void FrameLoader::started()
1667 {
1668     for (Frame* frame = m_frame; frame; frame = frame->tree()->parent())
1669         frame->loader()->m_isComplete = false;
1670 }
1671
1672 bool FrameLoader::containsPlugins() const 
1673
1674     return m_containsPlugIns;
1675 }
1676
1677 void FrameLoader::prepareForLoadStart()
1678 {
1679     if (m_frame->page())
1680         m_frame->page()->progress()->progressStarted(m_frame);
1681     m_client->dispatchDidStartProvisionalLoad();
1682 }
1683
1684 void FrameLoader::setupForReplace()
1685 {
1686     setState(FrameStateProvisional);
1687     m_provisionalDocumentLoader = m_documentLoader;
1688     m_documentLoader = 0;
1689     detachChildren();
1690 }
1691
1692 void FrameLoader::setupForReplaceByMIMEType(const String& newMIMEType)
1693 {
1694     activeDocumentLoader()->setupForReplaceByMIMEType(newMIMEType);
1695 }
1696
1697 void FrameLoader::finalSetupForReplace(DocumentLoader* loader)
1698 {
1699     m_client->clearUnarchivingState(loader);
1700 }
1701
1702 void FrameLoader::load(const KURL& URL, Event* event)
1703 {
1704     load(ResourceRequest(URL), true, event, 0, HashMap<String, String>());
1705 }
1706
1707 void FrameLoader::load(const FrameLoadRequest& request, bool userGesture, Event* event,
1708     HTMLFormElement* submitForm, const HashMap<String, String>& formValues)
1709 {
1710     String referrer;
1711     String argsReferrer = request.resourceRequest().httpReferrer();
1712     if (!argsReferrer.isEmpty())
1713         referrer = argsReferrer;
1714     else
1715         referrer = m_outgoingReferrer;
1716  
1717     bool hideReferrer;
1718     if (!canLoad(request.resourceRequest().url(), referrer, hideReferrer))
1719         return;
1720     if (hideReferrer)
1721         referrer = String();
1722     
1723     Frame* targetFrame = m_frame->tree()->find(request.frameName());
1724     if (!canTarget(targetFrame))
1725         return;
1726         
1727     if (request.resourceRequest().httpMethod() != "POST") {
1728         FrameLoadType loadType;
1729         if (request.resourceRequest().cachePolicy() == ReloadIgnoringCacheData)
1730             loadType = FrameLoadTypeReload;
1731         else if (!userGesture)
1732             loadType = FrameLoadTypeInternal;
1733         else
1734             loadType = FrameLoadTypeStandard;    
1735     
1736         load(request.resourceRequest().url(), referrer, loadType, 
1737             request.frameName(), event, submitForm, formValues);
1738     } else
1739         post(request.resourceRequest().url(), referrer, request.frameName(), 
1740             request.resourceRequest().httpBody(), request.resourceRequest().httpContentType(), event, submitForm, formValues);
1741
1742     if (targetFrame && targetFrame != m_frame)
1743         targetFrame->page()->chrome()->focus();
1744 }
1745
1746 void FrameLoader::load(const KURL& URL, const String& referrer, FrameLoadType newLoadType,
1747     const String& frameName, Event* event, HTMLFormElement* form, const HashMap<String, String>& values)
1748 {
1749     bool isFormSubmission = !values.isEmpty();
1750     
1751     ResourceRequest request(URL);
1752     if (!referrer.isEmpty())
1753         request.setHTTPReferrer(referrer);
1754     addExtraFieldsToRequest(request, true, event || isFormSubmission);
1755     if (newLoadType == FrameLoadTypeReload)
1756         request.setCachePolicy(ReloadIgnoringCacheData);
1757
1758     ASSERT(newLoadType != FrameLoadTypeSame);
1759
1760     NavigationAction action(URL, newLoadType, isFormSubmission, event);
1761
1762     RefPtr<FormState> formState;
1763     if (form && !values.isEmpty())
1764         formState = FormState::create(form, values, m_frame);
1765     
1766     if (!frameName.isEmpty()) {
1767         if (Frame* targetFrame = m_frame->tree()->find(frameName))
1768             targetFrame->loader()->load(URL, referrer, newLoadType, String(), event, form, values);
1769         else
1770             checkNewWindowPolicy(action, request, formState.release(), frameName);
1771         return;
1772     }
1773
1774     RefPtr<DocumentLoader> oldDocumentLoader = m_documentLoader;
1775
1776     bool sameURL = shouldTreatURLAsSameAsCurrent(URL);
1777     
1778     // Make sure to do scroll to anchor processing even if the URL is
1779     // exactly the same so pages with '#' links and DHTML side effects
1780     // work properly.
1781     if (!isFormSubmission
1782         && newLoadType != FrameLoadTypeReload
1783         && newLoadType != FrameLoadTypeSame
1784         && !shouldReload(URL, url())
1785         // We don't want to just scroll if a link from within a
1786         // frameset is trying to reload the frameset into _top.
1787         && !m_frame->isFrameSet()) {
1788
1789         // Just do anchor navigation within the existing content.
1790         
1791         // We don't do this if we are submitting a form, explicitly reloading,
1792         // currently displaying a frameset, or if the new URL does not have a fragment.
1793         // These rules are based on what KHTML was doing in KHTMLPart::openURL.
1794         
1795         // FIXME: What about load types other than Standard and Reload?
1796         
1797         oldDocumentLoader->setTriggeringAction(action);
1798         stopPolicyCheck();
1799         checkNavigationPolicy(request, oldDocumentLoader.get(), formState.release(),
1800             callContinueFragmentScrollAfterNavigationPolicy, this);
1801     } else {
1802         // must grab this now, since this load may stop the previous load and clear this flag
1803         bool isRedirect = m_quickRedirectComing;
1804         load(request, action, newLoadType, formState.release());
1805         if (isRedirect) {
1806             m_quickRedirectComing = false;
1807             if (m_provisionalDocumentLoader)
1808                 m_provisionalDocumentLoader->setIsClientRedirect(true);
1809         } else if (sameURL)
1810             // Example of this case are sites that reload the same URL with a different cookie
1811             // driving the generated content, or a master frame with links that drive a target
1812             // frame, where the user has clicked on the same link repeatedly.
1813             m_loadType = FrameLoadTypeSame;
1814     }
1815 }
1816
1817 void FrameLoader::load(const ResourceRequest& request)
1818 {
1819     if (m_inStopAllLoaders)
1820         return;
1821     
1822     load(request, SubstituteData());
1823 }
1824
1825 void FrameLoader::load(const ResourceRequest& request, const SubstituteData& substituteData)
1826 {
1827     // FIXME: is this the right place to reset loadType? Perhaps this should be done after loading is finished or aborted.
1828     m_loadType = FrameLoadTypeStandard;
1829     load(m_client->createDocumentLoader(request, substituteData).get());
1830 }
1831
1832 void FrameLoader::load(const ResourceRequest& request, const String& frameName)
1833 {
1834     if (frameName.isEmpty()) {
1835         load(request);
1836         return;
1837     }
1838
1839     Frame* frame = m_frame->tree()->find(frameName);
1840     if (frame) {
1841         frame->loader()->load(request);
1842         return;
1843     }
1844
1845     checkNewWindowPolicy(NavigationAction(request.url(), NavigationTypeOther), request, 0, frameName);
1846 }
1847
1848 void FrameLoader::load(const ResourceRequest& request, const NavigationAction& action, FrameLoadType type, PassRefPtr<FormState> formState)
1849 {
1850     RefPtr<DocumentLoader> loader = m_client->createDocumentLoader(request, SubstituteData());
1851
1852     loader->setTriggeringAction(action);
1853     if (m_documentLoader)
1854         loader->setOverrideEncoding(m_documentLoader->overrideEncoding());
1855
1856     load(loader.get(), type, formState);
1857 }
1858
1859 void FrameLoader::load(DocumentLoader* newDocumentLoader)
1860 {
1861     ResourceRequest& r = newDocumentLoader->request();
1862     addExtraFieldsToRequest(r, true, false);
1863     FrameLoadType type;
1864
1865     if (shouldTreatURLAsSameAsCurrent(newDocumentLoader->originalRequest().url())) {
1866         r.setCachePolicy(ReloadIgnoringCacheData);
1867         type = FrameLoadTypeSame;
1868     } else
1869         type = FrameLoadTypeStandard;
1870
1871     if (m_documentLoader)
1872         newDocumentLoader->setOverrideEncoding(m_documentLoader->overrideEncoding());
1873     
1874     // When we loading alternate content for an unreachable URL that we're
1875     // visiting in the b/f list, we treat it as a reload so the b/f list 
1876     // is appropriately maintained.
1877     if (shouldReloadToHandleUnreachableURL(newDocumentLoader)) {
1878         ASSERT(type == FrameLoadTypeStandard);
1879         type = FrameLoadTypeReload;
1880     }
1881
1882     load(newDocumentLoader, type, 0);
1883 }
1884
1885 void FrameLoader::load(DocumentLoader* loader, FrameLoadType type, PassRefPtr<FormState> formState)
1886 {
1887     ASSERT(m_client->hasWebView());
1888
1889     // Unfortunately the view must be non-nil, this is ultimately due
1890     // to parser requiring a FrameView.  We should fix this dependency.
1891
1892     ASSERT(m_client->hasFrameView());
1893
1894     m_policyLoadType = type;
1895
1896     if (Frame* parent = m_frame->tree()->parent())
1897         loader->setOverrideEncoding(parent->loader()->documentLoader()->overrideEncoding());
1898
1899     stopPolicyCheck();
1900     setPolicyDocumentLoader(loader);
1901
1902     checkNavigationPolicy(loader->request(), loader, formState,
1903         callContinueLoadAfterNavigationPolicy, this);
1904 }
1905
1906 bool FrameLoader::canLoad(const KURL& url, const String& referrer, bool& hideReferrer)
1907 {
1908     hideReferrer = shouldHideReferrer(url, referrer);
1909
1910     if (!shouldTreatURLAsLocal(url.url()))
1911         return true;
1912
1913     return shouldTreatURLAsLocal(referrer);
1914 }
1915
1916 bool FrameLoader::canLoad(const KURL& url, const Document* doc)
1917 {
1918     if (!shouldTreatURLAsLocal(url.url()))
1919         return true;
1920
1921     return doc && doc->isAllowedToLoadLocalResources();
1922 }
1923
1924 bool FrameLoader::canLoad(const CachedResource& resource, const Document* doc)
1925 {
1926     if (!resource.treatAsLocal())
1927         return true;
1928
1929     return doc && doc->isAllowedToLoadLocalResources();
1930 }
1931
1932 bool FrameLoader::shouldHideReferrer(const KURL& url, const String& referrer)
1933 {
1934     bool referrerIsSecureURL = referrer.startsWith("https:", false);
1935     bool referrerIsWebURL = referrerIsSecureURL || referrer.startsWith("http:", false);
1936
1937     if (!referrerIsWebURL)
1938         return true;
1939
1940     if (!referrerIsSecureURL)
1941         return false;
1942
1943     bool URLIsSecureURL = url.url().startsWith("https:", false);
1944
1945     return !URLIsSecureURL;
1946 }
1947
1948 const ResourceRequest& FrameLoader::initialRequest() const
1949 {
1950     return activeDocumentLoader()->initialRequest();
1951 }
1952
1953 void FrameLoader::receivedData(const char* data, int length)
1954 {
1955     activeDocumentLoader()->receivedData(data, length);
1956 }
1957
1958 bool FrameLoader::willUseArchive(ResourceLoader* loader, const ResourceRequest& request, const KURL& originalURL) const
1959 {
1960     return m_client->willUseArchive(loader, request, originalURL);
1961 }
1962
1963 void FrameLoader::handleUnimplementablePolicy(const ResourceError& error)
1964 {
1965     m_delegateIsHandlingUnimplementablePolicy = true;
1966     m_client->dispatchUnableToImplementPolicy(error);
1967     m_delegateIsHandlingUnimplementablePolicy = false;
1968 }
1969
1970 void FrameLoader::cannotShowMIMEType(const ResourceResponse& response)
1971 {
1972     handleUnimplementablePolicy(m_client->cannotShowMIMETypeError(response));
1973 }
1974
1975 ResourceError FrameLoader::interruptionForPolicyChangeError(const ResourceRequest& request)
1976 {
1977     return m_client->interruptForPolicyChangeError(request);
1978 }
1979
1980 void FrameLoader::checkNavigationPolicy(const ResourceRequest& newRequest, NavigationPolicyDecisionFunction function, void* argument)
1981 {
1982     checkNavigationPolicy(newRequest, activeDocumentLoader(), 0, function, argument);
1983 }
1984
1985 void FrameLoader::checkContentPolicy(const String& MIMEType, ContentPolicyDecisionFunction function, void* argument)
1986 {
1987     ASSERT(activeDocumentLoader());
1988     
1989     // Always show content with valid substitute data.
1990     if (activeDocumentLoader()->substituteData().isValid()) {
1991         function(argument, PolicyUse);
1992         return;
1993     }
1994
1995     m_policyCheck.set(function, argument);
1996     m_client->dispatchDecidePolicyForMIMEType(&FrameLoader::continueAfterContentPolicy,
1997         MIMEType, activeDocumentLoader()->request());
1998 }
1999
2000 bool FrameLoader::shouldReloadToHandleUnreachableURL(DocumentLoader* docLoader)
2001 {
2002     KURL unreachableURL = docLoader->unreachableURL();
2003
2004     if (unreachableURL.isEmpty())
2005         return false;
2006
2007     if (!isBackForwardLoadType(m_policyLoadType))
2008         return false;
2009
2010     // We only treat unreachableURLs specially during the delegate callbacks
2011     // for provisional load errors and navigation policy decisions. The former
2012     // case handles well-formed URLs that can't be loaded, and the latter
2013     // case handles malformed URLs and unknown schemes. Loading alternate content
2014     // at other times behaves like a standard load.
2015     DocumentLoader* compareDocumentLoader = 0;
2016     if (m_delegateIsDecidingNavigationPolicy || m_delegateIsHandlingUnimplementablePolicy)
2017         compareDocumentLoader = m_policyDocumentLoader.get();
2018     else if (m_delegateIsHandlingProvisionalLoadError)
2019         compareDocumentLoader = m_provisionalDocumentLoader.get();
2020
2021     return compareDocumentLoader && unreachableURL == compareDocumentLoader->request().url();
2022 }
2023
2024 void FrameLoader::reloadAllowingStaleData(const String& encoding)
2025 {
2026     if (!m_documentLoader)
2027         return;
2028
2029     ResourceRequest request = m_documentLoader->request();
2030     KURL unreachableURL = m_documentLoader->unreachableURL();
2031     if (!unreachableURL.isEmpty())
2032         request.setURL(unreachableURL);
2033
2034     request.setCachePolicy(ReturnCacheDataElseLoad);
2035
2036     RefPtr<DocumentLoader> loader = m_client->createDocumentLoader(request, SubstituteData());
2037     setPolicyDocumentLoader(loader.get());
2038
2039     loader->setOverrideEncoding(encoding);
2040
2041     load(loader.get(), FrameLoadTypeReloadAllowingStaleData, 0);
2042 }
2043
2044 void FrameLoader::reload()
2045 {
2046     if (!m_documentLoader)
2047         return;
2048
2049     ResourceRequest& initialRequest = m_documentLoader->request();
2050     
2051     // If a window is created by javascript, its main frame can have an empty but non-nil URL.
2052     // Reloading in this case will lose the current contents (see 4151001).
2053     if (initialRequest.url().isEmpty())
2054         return;
2055
2056     // Replace error-page URL with the URL we were trying to reach.
2057     KURL unreachableURL = m_documentLoader->unreachableURL();
2058     if (!unreachableURL.isEmpty())
2059         initialRequest = ResourceRequest(unreachableURL);
2060     
2061     RefPtr<DocumentLoader> loader = m_client->createDocumentLoader(initialRequest, SubstituteData());
2062
2063     ResourceRequest& request = loader->request();
2064
2065     request.setCachePolicy(ReloadIgnoringCacheData);
2066     request.setHTTPHeaderField("Cache-Control", "max-age=0");
2067
2068     // If we're about to re-post, set up action so the application can warn the user.
2069     if (request.httpMethod() == "POST")
2070         loader->setTriggeringAction(NavigationAction(request.url(), NavigationTypeFormResubmitted));
2071
2072     loader->setOverrideEncoding(m_documentLoader->overrideEncoding());
2073     
2074     load(loader.get(), FrameLoadTypeReload, 0);
2075 }
2076
2077 bool FrameLoader::canTarget(Frame* target) const
2078 {
2079     // This method prevents this exploit:
2080     // <rdar://problem/3715785> multiple frame injection vulnerability reported by Secunia, affects almost all browsers
2081
2082     if (!target)
2083         return true;
2084
2085     // Allow with navigation within the same page/frameset.
2086     if (m_frame->page() == target->page())
2087         return true;
2088
2089     String domain;
2090     if (Document* document = m_frame->document())
2091         domain = document->domain();
2092     // Allow if the request is made from a local file.
2093     if (domain.isEmpty())
2094         return true;
2095     
2096     Frame* parent = target->tree()->parent();
2097     // Allow if target is an entire window.
2098     if (!parent)
2099         return true;
2100     
2101     String parentDomain;
2102     if (Document* parentDocument = parent->document())
2103         domain = parentDocument->domain();
2104     // Allow if the domain of the parent of the targeted frame equals this domain.
2105     return equalIgnoringCase(parentDomain, domain);
2106 }
2107
2108 void FrameLoader::stopLoadingSubframes()
2109 {
2110     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
2111         child->loader()->stopAllLoaders();
2112 }
2113
2114 void FrameLoader::stopAllLoaders()
2115 {
2116     // If this method is called from within this method, infinite recursion can occur (3442218). Avoid this.
2117     if (m_inStopAllLoaders)
2118         return;
2119
2120     m_inStopAllLoaders = true;
2121
2122     stopPolicyCheck();
2123
2124     stopLoadingSubframes();
2125     if (m_provisionalDocumentLoader)
2126         m_provisionalDocumentLoader->stopLoading();
2127     if (m_documentLoader)
2128         m_documentLoader->stopLoading();
2129     setProvisionalDocumentLoader(0);
2130     m_client->clearArchivedResources();
2131
2132     m_inStopAllLoaders = false;    
2133 }
2134
2135 void FrameLoader::cancelPendingArchiveLoad(ResourceLoader* loader)
2136 {
2137     m_client->cancelPendingArchiveLoad(loader);
2138 }
2139
2140 DocumentLoader* FrameLoader::activeDocumentLoader() const
2141 {
2142     if (m_state == FrameStateProvisional)
2143         return m_provisionalDocumentLoader.get();
2144     return m_documentLoader.get();
2145 }
2146
2147 bool FrameLoader::isLoading() const
2148 {
2149     if (m_isLoadingMainResource)
2150         return true;
2151     DocumentLoader* docLoader = activeDocumentLoader();
2152     if (!docLoader)
2153         return false;
2154     return docLoader->isLoadingSubresources() || docLoader->isLoadingPlugIns();
2155 }
2156
2157 void FrameLoader::setDocumentLoader(DocumentLoader* loader)
2158 {
2159     if (!loader && !m_documentLoader)
2160         return;
2161     
2162     ASSERT(loader != m_documentLoader);
2163     ASSERT(!loader || loader->frameLoader() == this);
2164
2165     m_client->prepareForDataSourceReplacement();
2166     if (m_documentLoader)
2167         m_documentLoader->detachFromFrame();
2168
2169     m_documentLoader = loader;
2170 }
2171
2172 DocumentLoader* FrameLoader::documentLoader() const
2173 {
2174     return m_documentLoader.get();
2175 }
2176
2177 void FrameLoader::setPolicyDocumentLoader(DocumentLoader* loader)
2178 {
2179     if (m_policyDocumentLoader == loader)
2180         return;
2181
2182     ASSERT(m_frame);
2183     if (loader)
2184         loader->setFrame(m_frame);
2185     if (m_policyDocumentLoader
2186             && m_policyDocumentLoader != m_provisionalDocumentLoader
2187             && m_policyDocumentLoader != m_documentLoader)
2188         m_policyDocumentLoader->detachFromFrame();
2189
2190     m_policyDocumentLoader = loader;
2191 }
2192    
2193 DocumentLoader* FrameLoader::provisionalDocumentLoader()
2194 {
2195     return m_provisionalDocumentLoader.get();
2196 }
2197
2198 void FrameLoader::setProvisionalDocumentLoader(DocumentLoader* loader)
2199 {
2200     ASSERT(!loader || !m_provisionalDocumentLoader);
2201     ASSERT(!loader || loader->frameLoader() == this);
2202
2203     if (m_provisionalDocumentLoader && m_provisionalDocumentLoader != m_documentLoader)
2204         m_provisionalDocumentLoader->detachFromFrame();
2205
2206     m_provisionalDocumentLoader = loader;
2207 }
2208
2209 FrameState FrameLoader::state() const
2210 {
2211     return m_state;
2212 }
2213
2214 double FrameLoader::timeOfLastCompletedLoad()
2215 {
2216     return storedTimeOfLastCompletedLoad;
2217 }
2218
2219 void FrameLoader::setState(FrameState newState)
2220 {    
2221     m_state = newState;
2222     
2223     if (newState == FrameStateProvisional)
2224         provisionalLoadStarted();
2225     else if (newState == FrameStateComplete) {
2226         frameLoadCompleted();
2227         storedTimeOfLastCompletedLoad = currentTime();
2228         if (m_documentLoader)
2229             m_documentLoader->stopRecordingResponses();
2230     }
2231 }
2232
2233 void FrameLoader::clearProvisionalLoad()
2234 {
2235     setProvisionalDocumentLoader(0);
2236     if (m_frame->page())
2237         m_frame->page()->progress()->progressCompleted(m_frame);
2238     setState(FrameStateComplete);
2239 }
2240
2241 void FrameLoader::markLoadComplete()
2242 {
2243     setState(FrameStateComplete);
2244 }
2245
2246 void FrameLoader::commitProvisionalLoad()
2247 {
2248     if (m_documentLoader)
2249         m_documentLoader->stopLoadingSubresources();
2250     if (m_documentLoader)
2251         m_documentLoader->stopLoadingPlugIns();
2252
2253     setDocumentLoader(m_provisionalDocumentLoader.get());
2254     setProvisionalDocumentLoader(0);
2255     setState(FrameStateCommittedPage);
2256 }
2257
2258 void FrameLoader::commitProvisionalLoad(PassRefPtr<PageCache> prpPageCache)
2259 {
2260     RefPtr<PageCache> pageCache = prpPageCache;
2261     RefPtr<DocumentLoader> pdl = m_provisionalDocumentLoader;
2262     
2263     if (m_loadType != FrameLoadTypeReplace)
2264         closeOldDataSources();
2265     
2266     if (!pageCache)
2267         m_client->makeRepresentation(pdl.get());
2268     
2269     transitionToCommitted(pageCache);
2270     
2271     // Call -_clientRedirectCancelledOrFinished: here so that the frame load delegate is notified that the redirect's
2272     // status has changed, if there was a redirect.  The frame load delegate may have saved some state about
2273     // the redirect in its -webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:.  Since we are
2274     // just about to commit a new page, there cannot possibly be a pending redirect at this point.
2275     if (m_sentRedirectNotification)
2276         clientRedirectCancelledOrFinished(false);
2277     
2278     RefPtr<PageState> pageState;
2279     if (pageCache)
2280         pageState = pageCache->pageState();
2281     if (pageState) {
2282         open(*pageState);
2283         pageState->clear();
2284     } else {        
2285         KURL url = pdl->URL();
2286         if (url.isEmpty())
2287             url = pdl->responseURL();
2288         if (url.isEmpty())
2289             url = "about:blank";
2290
2291         didOpenURL(url);
2292     }
2293     opened();
2294 }
2295
2296 void FrameLoader::transitionToCommitted(PassRefPtr<PageCache> pageCache)
2297 {
2298     ASSERT(m_client->hasWebView());
2299     ASSERT(m_state == FrameStateProvisional);
2300
2301     if (m_state != FrameStateProvisional)
2302         return;
2303
2304     m_client->setCopiesOnScroll();
2305     updateHistoryForCommit();
2306
2307     // The call to closeURL() invokes the unload event handler, which can execute arbitrary
2308     // JavaScript. If the script initiates a new load, we need to abandon the current load,
2309     // or the two will stomp each other.
2310     DocumentLoader* pdl = m_provisionalDocumentLoader.get();
2311     closeURL();
2312     if (pdl != m_provisionalDocumentLoader)
2313         return;
2314
2315     commitProvisionalLoad();
2316
2317     // Handle adding the URL to the back/forward list.
2318     DocumentLoader* dl = m_documentLoader.get();
2319     String ptitle = dl->title();
2320
2321     switch (m_loadType) {
2322         case FrameLoadTypeForward:
2323         case FrameLoadTypeBack:
2324         case FrameLoadTypeIndexedBackForward:
2325             if (m_frame->page()->backForwardList()) {
2326                 updateHistoryForBackForwardNavigation();
2327
2328                 // Create a document view for this document, or used the cached view.
2329                 if (pageCache)
2330                     m_client->setDocumentViewFromPageCache(pageCache.get());
2331                 else
2332                     m_client->makeDocumentView();
2333             }
2334             break;
2335
2336         case FrameLoadTypeReload:
2337         case FrameLoadTypeSame:
2338         case FrameLoadTypeReplace:
2339             updateHistoryForReload();
2340             m_client->makeDocumentView();
2341             break;
2342
2343         // FIXME - just get rid of this case, and merge FrameLoadTypeReloadAllowingStaleData with the above case
2344         case FrameLoadTypeReloadAllowingStaleData:
2345             m_client->makeDocumentView();
2346             break;
2347
2348         case FrameLoadTypeStandard:
2349             updateHistoryForStandardLoad();
2350             m_client->makeDocumentView();
2351             break;
2352
2353         case FrameLoadTypeInternal:
2354             updateHistoryForInternalLoad();
2355             m_client->makeDocumentView();
2356             break;
2357
2358         // FIXME Remove this check when dummy ds is removed (whatever "dummy ds" is).
2359         // An exception should be thrown if we're in the FrameLoadTypeUninitialized state.
2360         default:
2361             ASSERT_NOT_REACHED();
2362     }
2363
2364     m_responseMIMEType = dl->responseMIMEType();
2365
2366     // Tell the client we've committed this URL.
2367     ASSERT(m_client->hasFrameView());
2368     m_client->dispatchDidCommitLoad();
2369     
2370     // If we have a title let the WebView know about it.
2371     if (!ptitle.isNull())
2372         m_client->dispatchDidReceiveTitle(ptitle);
2373 }
2374
2375 bool FrameLoader::privateBrowsingEnabled() const
2376 {
2377     return m_client->privateBrowsingEnabled();
2378 }
2379
2380 void FrameLoader::clientRedirectCancelledOrFinished(bool cancelWithLoadInProgress)
2381 {
2382     // Note that -webView:didCancelClientRedirectForFrame: is called on the frame load delegate even if
2383     // the redirect succeeded.  We should either rename this API, or add a new method, like
2384     // -webView:didFinishClientRedirectForFrame:
2385     m_client->dispatchDidCancelClientRedirect();
2386
2387     if (!cancelWithLoadInProgress)
2388         m_quickRedirectComing = false;
2389
2390     m_sentRedirectNotification = false;
2391 }
2392
2393 void FrameLoader::clientRedirected(const KURL& URL, double seconds, double fireDate, bool lockHistory, bool isJavaScriptFormAction)
2394 {
2395     m_client->dispatchWillPerformClientRedirect(URL, seconds, fireDate);
2396     
2397     // Remember that we sent a redirect notification to the frame load delegate so that when we commit
2398     // the next provisional load, we can send a corresponding -webView:didCancelClientRedirectForFrame:
2399     m_sentRedirectNotification = true;
2400     
2401     // If a "quick" redirect comes in an, we set a special mode so we treat the next
2402     // load as part of the same navigation. If we don't have a document loader, we have
2403     // no "original" load on which to base a redirect, so we treat the redirect as a normal load.
2404     m_quickRedirectComing = lockHistory && m_documentLoader && !isJavaScriptFormAction;
2405 }
2406
2407 bool FrameLoader::shouldReload(const KURL& currentURL, const KURL& destinationURL)
2408 {
2409     // This function implements the rule: "Don't reload if navigating by fragment within
2410     // the same URL, but do reload if going to a new URL or to the same URL with no
2411     // fragment identifier at all."
2412     if (!currentURL.hasRef() && !destinationURL.hasRef())
2413         return true;
2414     return !equalIgnoringRef(currentURL, destinationURL);
2415 }
2416
2417 void FrameLoader::closeOldDataSources()
2418 {
2419     // FIXME: Is it important for this traversal to be postorder instead of preorder?
2420     // If so, add helpers for postorder traversal, and use them. If not, then lets not
2421     // use a recursive algorithm here.
2422     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
2423         child->loader()->closeOldDataSources();
2424     
2425     if (m_documentLoader)
2426         m_client->dispatchWillClose();
2427
2428     m_client->setMainFrameDocumentReady(false); // stop giving out the actual DOMDocument to observers
2429 }
2430
2431 void FrameLoader::open(PageState& state)
2432 {
2433     ASSERT(m_frame->page()->mainFrame() == m_frame);
2434
2435     cancelRedirection();
2436
2437     // We still have to close the previous part page.
2438     closeURL();
2439
2440     m_isComplete = false;
2441     
2442     // Don't re-emit the load event.
2443     m_wasLoadEventEmitted = true;
2444     
2445     // Delete old status bar messages (if it _was_ activated on last URL).
2446     if (m_frame->settings()->isJavaScriptEnabled()) {
2447         m_frame->d->m_kjsStatusBarText = String();
2448         m_frame->d->m_kjsDefaultStatusBarText = String();
2449     }
2450
2451     KURL URL = state.URL();
2452
2453     if (URL.protocol().startsWith("http") && !URL.host().isEmpty() && URL.path().isEmpty())
2454         URL.setPath("/");
2455     
2456     m_URL = URL;
2457     m_workingURL = URL;
2458
2459     started();
2460
2461     clear();
2462
2463     Document* document = state.document();
2464     ASSERT(document);
2465     document->setInPageCache(false);
2466
2467     m_needsClear = true;
2468     m_isComplete = false;
2469     m_wasLoadEventEmitted = false;
2470     m_outgoingReferrer = URL.url();
2471     
2472     m_frame->setView(document->view());
2473     
2474     m_frame->d->m_doc = document;
2475     m_decoder = document->decoder();
2476
2477     updatePolicyBaseURL();
2478
2479     state.restore(m_frame->page());
2480
2481     checkCompleted();
2482 }
2483
2484 bool FrameLoader::isStopping() const
2485 {
2486     return activeDocumentLoader()->isStopping();
2487 }
2488
2489 void FrameLoader::finishedLoading()
2490 {
2491     // Retain because the stop may release the last reference to it.
2492     RefPtr<Frame> protect(m_frame);
2493
2494     RefPtr<DocumentLoader> dl = activeDocumentLoader();
2495     dl->finishedLoading();
2496     if (!dl->mainDocumentError().isNull() || !dl->frameLoader())
2497         return;
2498     dl->setPrimaryLoadComplete(true);
2499     m_client->dispatchDidLoadMainResource(dl.get());
2500     checkLoadComplete();
2501 }
2502
2503 KURL FrameLoader::URL() const
2504 {
2505     return activeDocumentLoader()->URL();
2506 }
2507
2508 bool FrameLoader::isArchiveLoadPending(ResourceLoader* loader) const
2509 {
2510     return m_client->isArchiveLoadPending(loader);
2511 }
2512
2513 bool FrameLoader::isHostedByObjectElement() const
2514 {
2515     HTMLFrameOwnerElement* owner = m_frame->ownerElement();
2516     return owner && owner->hasTagName(objectTag);
2517 }
2518
2519 bool FrameLoader::isLoadingMainFrame() const
2520 {
2521     Page* page = m_frame->page();
2522     return page && m_frame == page->mainFrame();
2523 }
2524
2525 bool FrameLoader::canShowMIMEType(const String& MIMEType) const
2526 {
2527     return m_client->canShowMIMEType(MIMEType);
2528 }
2529
2530 bool FrameLoader::representationExistsForURLScheme(const String& URLScheme)
2531 {
2532     return m_client->representationExistsForURLScheme(URLScheme);
2533 }
2534
2535 String FrameLoader::generatedMIMETypeForURLScheme(const String& URLScheme)
2536 {
2537     return m_client->generatedMIMETypeForURLScheme(URLScheme);
2538 }
2539
2540 void FrameLoader::cancelContentPolicyCheck()
2541 {
2542     m_client->cancelPolicyCheck();
2543     m_policyCheck.clear();
2544 }
2545
2546 void FrameLoader::didReceiveServerRedirectForProvisionalLoadForFrame()
2547 {
2548     m_client->dispatchDidReceiveServerRedirectForProvisionalLoad();
2549 }
2550
2551 void FrameLoader::finishedLoadingDocument(DocumentLoader* loader)
2552 {
2553     m_client->finishedLoading(loader);
2554 }
2555
2556 bool FrameLoader::isReplacing() const
2557 {
2558     return m_loadType == FrameLoadTypeReplace;
2559 }
2560
2561 void FrameLoader::setReplacing()
2562 {
2563     m_loadType = FrameLoadTypeReplace;
2564 }
2565
2566 void FrameLoader::revertToProvisional(DocumentLoader* loader)
2567 {
2568     m_client->revertToProvisionalState(loader);
2569 }
2570
2571 bool FrameLoader::subframeIsLoading() const
2572 {
2573     // It's most likely that the last added frame is the last to load so we walk backwards.
2574     for (Frame* child = m_frame->tree()->lastChild(); child; child = child->tree()->previousSibling()) {
2575         FrameLoader* childLoader = child->loader();
2576         DocumentLoader* documentLoader = childLoader->documentLoader();
2577         if (documentLoader && documentLoader->isLoadingInAPISense())
2578             return true;
2579         documentLoader = childLoader->provisionalDocumentLoader();
2580         if (documentLoader && documentLoader->isLoadingInAPISense())
2581             return true;
2582     }
2583     return false;
2584 }
2585
2586 void FrameLoader::willChangeTitle(DocumentLoader* loader)
2587 {
2588     m_client->willChangeTitle(loader);
2589 }
2590
2591 FrameLoadType FrameLoader::loadType() const
2592 {
2593     return m_loadType;
2594 }
2595
2596 void FrameLoader::stopPolicyCheck()
2597 {
2598     m_client->cancelPolicyCheck();
2599     PolicyCheck check = m_policyCheck;
2600     m_policyCheck.clear();
2601     check.cancel();
2602 }
2603
2604 void FrameLoader::checkLoadCompleteForThisFrame()
2605 {
2606     ASSERT(m_client->hasWebView());
2607
2608     switch (m_state) {
2609         case FrameStateProvisional: {
2610             if (m_delegateIsHandlingProvisionalLoadError)
2611                 return;
2612
2613             RefPtr<DocumentLoader> pdl = m_provisionalDocumentLoader;
2614             if (!pdl)
2615                 return;
2616                 
2617             // If we've received any errors we may be stuck in the provisional state and actually complete.
2618             const ResourceError& error = pdl->mainDocumentError();
2619             if (error.isNull())
2620                 return;
2621
2622             // Check all children first.
2623             RefPtr<HistoryItem> item;
2624             if (isBackForwardLoadType(loadType()) && m_frame == m_frame->page()->mainFrame())
2625                 item = m_currentHistoryItem;
2626                 
2627             bool shouldReset = true;
2628             if (!pdl->isLoadingInAPISense()) {
2629                 m_delegateIsHandlingProvisionalLoadError = true;
2630                 m_client->dispatchDidFailProvisionalLoad(error);
2631                 m_delegateIsHandlingProvisionalLoadError = false;
2632
2633                 // FIXME: can stopping loading here possibly have any effect, if isLoading is false,
2634                 // which it must be to be in this branch of the if? And is it OK to just do a full-on
2635                 // stopAllLoaders instead of stopLoadingSubframes?
2636                 stopLoadingSubframes();
2637                 pdl->stopLoading();
2638
2639                 // Finish resetting the load state, but only if another load hasn't been started by the
2640                 // delegate callback.
2641                 if (pdl == m_provisionalDocumentLoader)
2642                     clearProvisionalLoad();
2643                 else {
2644                     KURL unreachableURL = m_provisionalDocumentLoader->unreachableURL();
2645                     if (!unreachableURL.isEmpty() && unreachableURL == pdl->request().url())
2646                         shouldReset = false;
2647                 }
2648             }
2649             if (shouldReset && item && m_frame->page())
2650                  m_frame->page()->backForwardList()->goToItem(item.get());
2651
2652             return;
2653         }
2654         
2655         case FrameStateCommittedPage: {
2656             DocumentLoader* dl = m_documentLoader.get();            
2657             if (dl->isLoadingInAPISense())
2658                 return;
2659
2660             markLoadComplete();
2661
2662             // FIXME: Is this subsequent work important if we already navigated away?
2663             // Maybe there are bugs because of that, or extra work we can skip because
2664             // the new page is ready.
2665
2666             m_client->forceLayoutForNonHTML();
2667              
2668             // If the user had a scroll point, scroll to it, overriding the anchor point if any.
2669             if ((isBackForwardLoadType(m_loadType) || m_loadType == FrameLoadTypeReload)
2670                     && m_frame->page() && m_frame->page()->backForwardList())
2671                 restoreScrollPositionAndViewState();
2672
2673             const ResourceError& error = dl->mainDocumentError();
2674             if (!error.isNull())
2675                 m_client->dispatchDidFailLoad(error);
2676             else
2677                 m_client->dispatchDidFinishLoad();
2678
2679             if (m_frame->page())
2680                 m_frame->page()->progress()->progressCompleted(m_frame);
2681             return;
2682         }
2683         
2684         case FrameStateComplete:
2685             // Even if already complete, we might have set a previous item on a frame that
2686             // didn't do any data loading on the past transaction. Make sure to clear these out.
2687             m_client->frameLoadCompleted();
2688             return;
2689     }
2690
2691     ASSERT_NOT_REACHED();
2692 }
2693
2694 void FrameLoader::continueAfterContentPolicy(PolicyAction policy)
2695 {
2696     PolicyCheck check = m_policyCheck;
2697     m_policyCheck.clear();
2698     check.call(policy);
2699 }
2700
2701 void FrameLoader::continueAfterWillSubmitForm(PolicyAction)
2702 {
2703     startLoading();
2704 }
2705
2706 void FrameLoader::didFirstLayout()
2707 {
2708     if (isBackForwardLoadType(m_loadType) && m_frame->page() && m_frame->page()->backForwardList())
2709         restoreScrollPositionAndViewState();
2710
2711     m_firstLayoutDone = true;
2712     m_client->dispatchDidFirstLayout();
2713 }
2714
2715 void FrameLoader::frameLoadCompleted()
2716 {
2717     m_client->frameLoadCompleted();
2718
2719     // After a canceled provisional load, firstLayoutDone is false.
2720     // Reset it to true if we're displaying a page.
2721     if (m_documentLoader)
2722         m_firstLayoutDone = true;
2723 }
2724
2725 bool FrameLoader::firstLayoutDone() const
2726 {
2727     return m_firstLayoutDone;
2728 }
2729
2730 bool FrameLoader::isQuickRedirectComing() const
2731 {
2732     return m_quickRedirectComing;
2733 }
2734
2735 void FrameLoader::detachChildren()
2736 {
2737     // FIXME: Is it really necessary to do this in reverse order?
2738     Frame* previous;
2739     for (Frame* child = m_frame->tree()->lastChild(); child; child = previous) {
2740         previous = child->tree()->previousSibling();
2741         child->loader()->detachFromParent();
2742     }
2743 }
2744
2745 // Called every time a resource is completely loaded, or an error is received.
2746 void FrameLoader::checkLoadComplete()
2747 {
2748     ASSERT(m_client->hasWebView());
2749     for (RefPtr<Frame> frame = m_frame; frame; frame = frame->tree()->parent())
2750         frame->loader()->checkLoadCompleteForThisFrame();
2751 }
2752
2753 int FrameLoader::numPendingOrLoadingRequests(bool recurse) const
2754 {
2755     if (!recurse)
2756         return numRequests(m_frame->document());
2757
2758     int count = 0;
2759     for (Frame* frame = m_frame; frame; frame = frame->tree()->traverseNext(m_frame))
2760         count += numRequests(frame->document());
2761     return count;
2762 }
2763
2764 FrameLoaderClient* FrameLoader::client() const
2765 {
2766     return m_client;
2767 }
2768
2769 void FrameLoader::submitForm(const FrameLoadRequest& request, Event* event)
2770 {
2771     // FIXME: We'd like to remove this altogether and fix the multiple form submission issue another way.
2772     // We do not want to submit more than one form from the same page,
2773     // nor do we want to submit a single form more than once.
2774     // This flag prevents these from happening; not sure how other browsers prevent this.
2775     // The flag is reset in each time we start handle a new mouse or key down event, and
2776     // also in setView since this part may get reused for a page from the back/forward cache.
2777     // The form multi-submit logic here is only needed when we are submitting a form that affects this frame.
2778     // FIXME: Frame targeting is only one of the ways the submission could end up doing something other
2779     // than replacing this frame's content, so this check is flawed. On the other hand, the check is hardly
2780     // needed any more now that we reset m_submittedFormURL on each mouse or key down event.
2781     Frame* target = m_frame->tree()->find(request.frameName());
2782     if (m_frame->tree()->isDescendantOf(target)) {
2783         if (m_submittedFormURL == request.resourceRequest().url())
2784             return;
2785         m_submittedFormURL = request.resourceRequest().url();
2786     }
2787
2788     // FIXME: Why do we always pass true for userGesture?
2789     load(request, true, event, m_formAboutToBeSubmitted.get(), m_formValuesAboutToBeSubmitted);
2790
2791     clearRecordedFormValues();
2792 }
2793
2794 void FrameLoader::urlSelected(const FrameLoadRequest& request, Event* event)
2795 {
2796     FrameLoadRequest copy = request;
2797     if (copy.resourceRequest().httpReferrer().isEmpty())
2798         copy.resourceRequest().setHTTPReferrer(m_outgoingReferrer);
2799
2800     // FIXME: Why do we always pass true for userGesture?
2801     load(copy, true, event, 0, HashMap<String, String>());
2802 }
2803     
2804 String FrameLoader::userAgent(const KURL& url) const
2805 {
2806     return m_client->userAgent(url);
2807 }
2808
2809 void FrameLoader::createEmptyDocument()
2810 {
2811     // Although it's not completely clear from the name of this function,
2812     // it does nothing if we already have a document, and just creates an
2813     // empty one if we have no document at all.
2814     if (!m_frame->document()) {
2815         loadEmptyDocumentSynchronously();
2816         updateBaseURLForEmptyDocument();
2817     }
2818 }
2819
2820 void FrameLoader::tokenizerProcessedData()
2821 {
2822     if (m_frame->document())
2823         checkCompleted();
2824     checkLoadComplete();
2825 }
2826
2827 void FrameLoader::didTellBridgeAboutLoad(const String& URL)
2828 {
2829     m_urlsBridgeKnowsAbout.add(URL);
2830 }
2831
2832 bool FrameLoader::haveToldBridgeAboutLoad(const String& URL)
2833 {
2834     return m_urlsBridgeKnowsAbout.contains(URL);
2835 }
2836
2837 void FrameLoader::handledOnloadEvents()
2838 {
2839     m_client->dispatchDidHandleOnloadEvents();
2840 }
2841
2842 void FrameLoader::frameDetached()
2843 {
2844     stopAllLoaders();
2845     detachFromParent();
2846 }
2847
2848 void FrameLoader::detachFromParent()
2849 {
2850     RefPtr<Frame> protect(m_frame);
2851
2852     closeURL();
2853     stopAllLoaders();
2854     saveScrollPositionAndViewStateToItem(currentHistoryItem());
2855     detachChildren();
2856     m_client->detachedFromParent2();
2857     setDocumentLoader(0);
2858     m_client->detachedFromParent3();
2859     if (Frame* parent = m_frame->tree()->parent()) {
2860         parent->tree()->removeChild(m_frame);
2861         parent->loader()->scheduleCheckCompleted();
2862     } else {
2863         m_frame->setView(0);
2864         m_frame->pageDestroyed();
2865     }
2866 #if PLATFORM(MAC)
2867     [m_frame->bridge() close];
2868 #endif
2869     m_client->detachedFromParent4();
2870 }
2871
2872 void FrameLoader::dispatchDidChangeLocationWithinPage()
2873 {
2874     m_client->dispatchDidChangeLocationWithinPage();
2875 }
2876
2877 void FrameLoader::dispatchDidFinishLoadToClient()
2878 {
2879     m_client->didFinishLoad();
2880 }
2881
2882 void FrameLoader::updateGlobalHistoryForStandardLoad(const KURL& url)
2883 {
2884     m_client->updateGlobalHistoryForStandardLoad(url);
2885 }
2886
2887 void FrameLoader::updateGlobalHistoryForReload(const KURL& url)
2888 {
2889     m_client->updateGlobalHistoryForReload(url);
2890 }
2891
2892 bool FrameLoader::shouldGoToHistoryItem(HistoryItem* item) const
2893 {
2894     return m_client->shouldGoToHistoryItem(item);
2895 }
2896
2897 void FrameLoader::addExtraFieldsToRequest(ResourceRequest& request, bool mainResource, bool alwaysFromRequest)
2898 {
2899     applyUserAgent(request);
2900     
2901     if (m_loadType == FrameLoadTypeReload)
2902         request.setHTTPHeaderField("Cache-Control", "max-age=0");
2903     
2904     // Don't set the cookie policy URL if it's already been set.
2905     if (request.mainDocumentURL().isEmpty()) {
2906         if (mainResource && (isLoadingMainFrame() || alwaysFromRequest))
2907             request.setMainDocumentURL(request.url());
2908         else
2909             request.setMainDocumentURL(m_frame->page()->mainFrame()->loader()->url());
2910     }
2911     
2912     if (mainResource)
2913         request.setHTTPAccept("text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5");
2914 }
2915
2916 void FrameLoader::committedLoad(DocumentLoader* loader, const char* data, int length)
2917 {
2918     m_client->committedLoad(loader, data, length);
2919 }
2920
2921 void FrameLoader::post(const KURL& URL, const String& referrer, const String& frameName, PassRefPtr<FormData> formData, 
2922     const String& contentType, Event* event, HTMLFormElement* form, const HashMap<String, String>& formValues)
2923 {
2924     // When posting, use the NSURLRequestReloadIgnoringCacheData load flag.
2925     // This prevents a potential bug which may cause a page with a form that uses itself
2926     // as an action to be returned from the cache without submitting.
2927
2928     // FIXME: Where's the code that implements what the comment above says?
2929
2930     ResourceRequest request(URL);
2931     addExtraFieldsToRequest(request, true, true);
2932
2933     if (!referrer.isEmpty())
2934         request.setHTTPReferrer(referrer);
2935     request.setHTTPMethod("POST");
2936     request.setHTTPBody(formData);
2937     request.setHTTPContentType(contentType);
2938
2939     NavigationAction action(URL, FrameLoadTypeStandard, true, event);
2940
2941     RefPtr<FormState> formState;
2942     if (form && !formValues.isEmpty())
2943         formState = FormState::create(form, formValues, m_frame);
2944
2945     if (!frameName.isEmpty()) {
2946         if (Frame* targetFrame = m_frame->tree()->find(frameName))
2947             targetFrame->loader()->load(request, action, FrameLoadTypeStandard, formState.release());
2948         else
2949             checkNewWindowPolicy(action, request, formState.release(), frameName);
2950     } else
2951         load(request, action, FrameLoadTypeStandard, formState.release());
2952 }
2953
2954 bool FrameLoader::isReloading() const
2955 {
2956     return documentLoader()->request().cachePolicy() == ReloadIgnoringCacheData;
2957 }
2958
2959 void FrameLoader::loadEmptyDocumentSynchronously()
2960 {
2961     ResourceRequest request(KURL(""));
2962     load(request);
2963 }
2964
2965 void FrameLoader::loadResourceSynchronously(const ResourceRequest& request, ResourceError& error, ResourceResponse& response, Vector<char>& data)
2966 {
2967     // Since this is a subresource, we can load any URL (we ignore the return value).
2968     // But we still want to know whether we should hide the referrer or not, so we call the canLoad method.
2969     String referrer = m_outgoingReferrer;
2970     if (shouldHideReferrer(request.url(), referrer))
2971         referrer = String();
2972     
2973     ResourceRequest initialRequest = request;
2974     initialRequest.setTimeoutInterval(10);
2975     
2976     if (initialRequest.isConditional())
2977         initialRequest.setCachePolicy(ReloadIgnoringCacheData);
2978     else
2979         initialRequest.setCachePolicy(documentLoader()->request().cachePolicy());
2980     
2981     if (!referrer.isEmpty())
2982         initialRequest.setHTTPReferrer(referrer);
2983     
2984     initialRequest.setMainDocumentURL(m_frame->page()->mainFrame()->loader()->documentLoader()->request().url());
2985     initialRequest.setHTTPUserAgent(client()->userAgent(request.url()));
2986     
2987     unsigned long identifier = 0;    
2988     ResourceRequest newRequest(initialRequest);
2989     requestFromDelegate(newRequest, identifier, error);
2990
2991     if (error.isNull()) {
2992         ASSERT(!newRequest.isNull());
2993         didTellBridgeAboutLoad(newRequest.url().url());
2994         ResourceHandle::loadResourceSynchronously(newRequest, error, response, data);
2995     }
2996     
2997     sendRemainingDelegateMessages(identifier, response, data.size(), error);
2998 }
2999
3000 // FIXME: Poor method name; also, why is this not part of startProvisionalLoad:?
3001 void FrameLoader::startLoading()
3002 {
3003     if (!m_provisionalDocumentLoader)
3004         return;
3005
3006     m_provisionalDocumentLoader->prepareForLoadStart();
3007
3008     DocumentLoader* activeDocLoader = activeDocumentLoader();
3009     if (activeDocLoader && activeDocLoader->isLoadingMainResource())
3010         return;
3011
3012     m_provisionalDocumentLoader->setLoadingFromPageCache(false);
3013
3014     unsigned long identifier = m_frame->page()->progress()->createUniqueIdentifier();
3015     m_client->assignIdentifierToInitialRequest(identifier, m_provisionalDocumentLoader.get(), m_provisionalDocumentLoader->originalRequest());
3016
3017     if (!m_provisionalDocumentLoader->startLoadingMainResource(identifier))
3018         m_provisionalDocumentLoader->updateLoading();
3019 }
3020
3021 void FrameLoader::assignIdentifierToInitialRequest(unsigned long identifier, const ResourceRequest& clientRequest)
3022 {
3023     return m_client->assignIdentifierToInitialRequest(identifier, activeDocumentLoader(), clientRequest);
3024 }
3025
3026 void FrameLoader::willSendRequest(ResourceLoader* loader, ResourceRequest& clientRequest, const ResourceResponse& redirectResponse)
3027 {
3028     applyUserAgent(clientRequest);
3029     m_client->dispatchWillSendRequest(loader->documentLoader(), loader->identifier(), clientRequest, redirectResponse);
3030 }
3031
3032 void FrameLoader::didReceiveResponse(ResourceLoader* loader, const ResourceResponse& r)
3033 {
3034     activeDocumentLoader()->addResponse(r);
3035     
3036     if (m_frame->page())
3037         m_frame->page()->progress()->incrementProgress(loader->identifier(), r);
3038     m_client->dispatchDidReceiveResponse(loader->documentLoader(), loader->identifier(), r);
3039 }
3040
3041 void FrameLoader::didReceiveData(ResourceLoader* loader, const char* data, int length, int lengthReceived)
3042 {
3043     if (m_frame->page())
3044         m_frame->page()->progress()->incrementProgress(loader->identifier(), data, length);
3045     m_client->dispatchDidReceiveContentLength(loader->documentLoader(), loader->identifier(), lengthReceived);
3046 }
3047
3048 void FrameLoader::didFailToLoad(ResourceLoader* loader, const ResourceError& error)
3049 {
3050     if (m_frame->page())
3051         m_frame->page()->progress()->completeProgress(loader->identifier());
3052     if (!error.isNull())
3053         m_client->dispatchDidFailLoading(loader->documentLoader(), loader->identifier(), error);
3054 }
3055
3056 const ResourceRequest& FrameLoader::originalRequest() const
3057 {
3058     return activeDocumentLoader()->originalRequestCopy();
3059 }
3060
3061 void FrameLoader::receivedMainResourceError(const ResourceError& error, bool isComplete)
3062 {
3063     // Retain because the stop may release the last reference to it.
3064     RefPtr<Frame> protect(m_frame);
3065
3066     RefPtr<DocumentLoader> loader = activeDocumentLoader();
3067     
3068     if (isComplete) {
3069         // FIXME: Don't want to do this if an entirely new load is going, so should check
3070         // that both data sources on the frame are either this or nil.
3071         stop();
3072         if (m_client->shouldFallBack(error))
3073             handleFallbackContent();
3074     }
3075     
3076     if (m_state == FrameStateProvisional) {
3077         KURL failedURL = m_provisionalDocumentLoader->originalRequestCopy().url();
3078         didNotOpenURL(failedURL);
3079             
3080         // We might have made a page cache item, but now we're bailing out due to an error before we ever
3081         // transitioned to the new page (before WebFrameState == commit).  The goal here is to restore any state
3082         // so that the existing view (that wenever got far enough to replace) can continue being used.
3083         Document* document = m_frame->document();
3084         if (document)
3085             document->setInPageCache(false);
3086         invalidateCurrentItemPageCache();
3087         
3088         // Call clientRedirectCancelledOrFinished here so that the frame load delegate is notified that the redirect's
3089         // status has changed, if there was a redirect. The frame load delegate may have saved some state about
3090         // the redirect in its -webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:. Since we are definitely
3091         // not going to use this provisional resource, as it was cancelled, notify the frame load delegate that the redirect
3092         // has ended.
3093         if (m_sentRedirectNotification)
3094             clientRedirectCancelledOrFinished(false);
3095     }
3096     
3097     
3098     loader->mainReceivedError(error, isComplete);
3099 }
3100
3101 void FrameLoader::callContinueFragmentScrollAfterNavigationPolicy(void* argument,
3102     const ResourceRequest& request, PassRefPtr<FormState>, bool shouldContinue)
3103 {
3104     FrameLoader* loader = static_cast<FrameLoader*>(argument);
3105     loader->continueFragmentScrollAfterNavigationPolicy(request, shouldContinue);
3106 }
3107
3108 void FrameLoader::continueFragmentScrollAfterNavigationPolicy(const ResourceRequest& request, bool shouldContinue)
3109 {
3110     bool isRedirect = m_quickRedirectComing;
3111     m_quickRedirectComing = false;
3112
3113     if (!shouldContinue)
3114         return;
3115
3116     KURL URL = request.url();
3117     
3118     m_documentLoader->replaceRequestURLForAnchorScroll(URL);
3119     if (!isRedirect && !shouldTreatURLAsSameAsCurrent(URL)) {
3120         // NB: must happen after _setURL, since we add based on the current request.
3121         // Must also happen before we openURL and displace the scroll position, since
3122         // adding the BF item will save away scroll state.
3123         
3124         // NB2:  If we were loading a long, slow doc, and the user anchor nav'ed before
3125         // it was done, currItem is now set the that slow doc, and prevItem is whatever was
3126         // before it.  Adding the b/f item will bump the slow doc down to prevItem, even
3127         // though its load is not yet done.  I think this all works out OK, for one because
3128         // we have already saved away the scroll and doc state for the long slow load,
3129         // but it's not an obvious case.
3130
3131         addHistoryItemForFragmentScroll();
3132     }
3133     
3134     scrollToAnchor(URL);
3135     
3136     if (!isRedirect)
3137         // This will clear previousItem from the rest of the frame tree that didn't
3138         // doing any loading. We need to make a pass on this now, since for anchor nav
3139         // we'll not go through a real load and reach Completed state.
3140         checkLoadComplete();
3141  
3142     dispatchDidChangeLocationWithinPage();
3143     m_client->didFinishLoad();
3144 }
3145
3146 void FrameLoader::opened()
3147 {
3148     if (m_loadType == FrameLoadTypeStandard && m_documentLoader->isClientRedirect())
3149         updateHistoryForClientRedirect();
3150
3151     if (m_documentLoader->isLoadingFromPageCache()) {
3152         // Force a layout to update view size and thereby update scrollbars.
3153         m_client->forceLayout();
3154
3155         const ResponseVector& responses = m_documentLoader->responses();
3156         size_t count = responses.size();
3157         for (size_t i = 0; i < count; i++) {
3158             const ResourceResponse& response = responses[i];
3159             // FIXME: If the WebKit client changes or cancels the request, this is not respected.
3160             ResourceError error;
3161             unsigned long identifier;
3162             ResourceRequest request(response.url());
3163             requestFromDelegate(request, identifier, error);
3164             sendRemainingDelegateMessages(identifier, response, response.expectedContentLength(), error);
3165         }
3166         
3167         m_client->loadedFromPageCache();
3168
3169         m_documentLoader->setPrimaryLoadComplete(true);
3170
3171         // FIXME: Why only this frame and not parent frames?
3172         checkLoadCompleteForThisFrame();
3173     }
3174 }
3175
3176 void FrameLoader::checkNewWindowPolicy(const NavigationAction& action, const ResourceRequest& request,
3177     PassRefPtr<FormState> formState, const String& frameName)
3178 {
3179     m_policyCheck.set(request, formState, frameName,
3180         callContinueLoadAfterNewWindowPolicy, this);
3181     m_client->dispatchDecidePolicyForNewWindowAction(&FrameLoader::continueAfterNewWindowPolicy,
3182         action, request, frameName);
3183 }
3184
3185 void FrameLoader::continueAfterNewWindowPolicy(PolicyAction policy)
3186 {
3187     PolicyCheck check = m_policyCheck;
3188     m_policyCheck.clear();
3189
3190     switch (policy) {
3191         case PolicyIgnore:
3192             check.clearRequest();
3193             break;
3194         case PolicyDownload:
3195             m_client->startDownload(check.request());
3196             check.clearRequest();
3197             break;
3198         case PolicyUse:
3199             break;
3200     }
3201
3202     check.call(policy == PolicyUse);
3203 }
3204
3205 void FrameLoader::checkNavigationPolicy(const ResourceRequest& request, DocumentLoader* loader,
3206     PassRefPtr<FormState> formState, NavigationPolicyDecisionFunction function, void* argument)
3207 {
3208     NavigationAction action = loader->triggeringAction();
3209     if (action.isEmpty()) {
3210         action = NavigationAction(request.url(), NavigationTypeOther);
3211         loader->setTriggeringAction(action);
3212     }
3213         
3214     // Don't ask more than once for the same request or if we are loading an empty URL.
3215     // This avoids confusion on the part of the client.
3216     if (request == loader->lastCheckedRequest() || request.url().isEmpty()) {
3217         function(argument, request, 0, true);
3218         return;
3219     }
3220     
3221     // We are always willing to show alternate content for unreachable URLs;
3222     // treat it like a reload so it maintains the right state for b/f list.
3223     if (loader->substituteData().isValid() && !loader->substituteData().failingURL().isEmpty()) {
3224         if (isBackForwardLoadType(m_policyLoadType))
3225             m_policyLoadType = FrameLoadTypeReload;
3226         function(argument, request, 0, true);
3227         return;
3228     }
3229     
3230     loader->setLastCheckedRequest(request);
3231
3232     m_policyCheck.set(request, formState, function, argument);
3233
3234     m_delegateIsDecidingNavigationPolicy = true;
3235     m_client->dispatchDecidePolicyForNavigationAction(&FrameLoader::continueAfterNavigationPolicy,
3236         action, request);
3237     m_delegateIsDecidingNavigationPolicy = false;
3238 }
3239
3240 void FrameLoader::continueAfterNavigationPolicy(PolicyAction policy)
3241 {
3242     PolicyCheck check = m_policyCheck;
3243     m_policyCheck.clear();
3244
3245     switch (policy) {
3246         case PolicyIgnore:
3247             check.clearRequest();
3248             break;
3249         case PolicyDownload:
3250             m_client->startDownload(check.request());
3251             check.clearRequest();
3252             break;
3253         case PolicyUse: {
3254             ResourceRequest request(check.request());
3255             if (!m_client->canHandleRequest(request)) {
3256                 handleUnimplementablePolicy(m_client->cannotShowURLError(check.request()));
3257                 check.clearRequest();
3258             }
3259             break;
3260         }
3261     }
3262
3263     check.call(policy == PolicyUse);
3264 }
3265
3266 void FrameLoader::callContinueLoadAfterNavigationPolicy(void* argument,
3267     const ResourceRequest& request, PassRefPtr<FormState> formState, bool shouldContinue)
3268 {
3269     FrameLoader* loader = static_cast<FrameLoader*>(argument);
3270     loader->continueLoadAfterNavigationPolicy(request, formState, shouldContinue);
3271 }
3272
3273 void FrameLoader::continueLoadAfterNavigationPolicy(const ResourceRequest& request, PassRefPtr<FormState> formState, bool shouldContinue)
3274 {
3275     // If we loaded an alternate page to replace an unreachableURL, we'll get in here with a
3276     // nil policyDataSource because loading the alternate page will have passed
3277     // through this method already, nested; otherwise, policyDataSource should still be set.
3278     ASSERT(m_policyDocumentLoader || !m_provisionalDocumentLoader->unreachableURL().isEmpty());
3279
3280     bool isTargetItem = m_provisionalHistoryItem ? m_provisionalHistoryItem->isTargetItem() : false;
3281
3282     // Two reasons we can't continue:
3283     //    1) Navigation policy delegate said we can't so request is nil. A primary case of this 
3284     //       is the user responding Cancel to the form repost nag sheet.
3285     //    2) User responded Cancel to an alert popped up by the before unload event handler.
3286     // The "before unload" event handler runs only for the main frame.
3287     bool canContinue = shouldContinue && (!isLoadingMainFrame() || m_frame->shouldClose());
3288
3289     if (!canContinue) {
3290         // If we were waiting for a quick redirect, but the policy delegate decided to ignore it, then we 
3291         // need to report that the client redirect was cancelled.
3292         if (m_quickRedirectComing)
3293             clientRedirectCancelledOrFinished(false);
3294
3295         setPolicyDocumentLoader(0);
3296
3297         // If the navigation request came from the back/forward menu, and we punt on it, we have the 
3298         // problem that we have optimistically moved the b/f cursor already, so move it back.  For sanity, 
3299         // we only do this when punting a navigation for the target frame or top-level frame.  
3300         if ((isTargetItem || isLoadingMainFrame()) && isBackForwardLoadType(m_policyLoadType) && m_frame->page()) {
3301             Frame* mainFrame = m_frame->page()->mainFrame();
3302             if (HistoryItem* resetItem = mainFrame->loader()->m_currentHistoryItem.get())
3303                 m_frame->page()->backForwardList()->goToItem(resetItem);
3304         }
3305         return;
3306     }
3307
3308     FrameLoadType type = m_policyLoadType;
3309     stopAllLoaders();
3310     setProvisionalDocumentLoader(m_policyDocumentLoader.get());
3311     m_loadType = type;
3312     setState(FrameStateProvisional);
3313
3314     setPolicyDocumentLoader(0);
3315
3316     if (isBackForwardLoadType(type) && loadProvisionalItemFromPageCache())
3317         return;
3318
3319     if (formState)
3320         m_client->dispatchWillSubmitForm(&FrameLoader::continueAfterWillSubmitForm, formState);
3321     else
3322         continueAfterWillSubmitForm();
3323 }
3324
3325
3326 void FrameLoader::callContinueLoadAfterNewWindowPolicy(void* argument,
3327     const ResourceRequest& request, PassRefPtr<FormState> formState, const String& frameName, bool shouldContinue)
3328 {
3329     FrameLoader* loader = static_cast<FrameLoader*>(argument);
3330     loader->continueLoadAfterNewWindowPolicy(request, formState, frameName, shouldContinue);
3331 }
3332
3333 void FrameLoader::continueLoadAfterNewWindowPolicy(const ResourceRequest& request,
3334     PassRefPtr<FormState> formState, const String& frameName, bool shouldContinue)
3335 {
3336     if (!shouldContinue)
3337         return;
3338
3339     RefPtr<Frame> frame = m_frame;
3340     RefPtr<Frame> mainFrame = m_client->dispatchCreatePage();
3341     if (!mainFrame)
3342         return;
3343
3344     if (frameName != "_blank")
3345         mainFrame->tree()->setName(frameName);
3346     mainFrame->loader()->m_client->dispatchShow();
3347     mainFrame->loader()->setOpener(frame.get());
3348     mainFrame->loader()->load(request, NavigationAction(), FrameLoadTypeStandard, formState);
3349 }
3350
3351 void FrameLoader::sendRemainingDelegateMessages(unsigned long identifier, const ResourceResponse& response, unsigned length, const ResourceError& error)
3352 {    
3353     if (!response.isNull())
3354         m_client->dispatchDidReceiveResponse(m_documentLoader.get(), identifier, response);
3355     
3356     if (length > 0)
3357         m_client->dispatchDidReceiveContentLength(m_documentLoader.get(), identifier, length);
3358     
3359     if (error.isNull())
3360         m_client->dispatchDidFinishLoading(m_documentLoader.get(), identifier);
3361     else
3362         m_client->dispatchDidFailLoading(m_documentLoader.get(), identifier, error);
3363 }
3364
3365 void FrameLoader::requestFromDelegate(ResourceRequest& request, unsigned long& identifier, ResourceError& error)
3366 {
3367     ASSERT(!request.isNull());
3368
3369     identifier = m_frame->page()->progress()->createUniqueIdentifier();
3370     m_client->assignIdentifierToInitialRequest(identifier, m_documentLoader.get(), request);
3371
3372     ResourceRequest newRequest(request);
3373     m_client->dispatchWillSendRequest(m_documentLoader.get(), identifier, newRequest, ResourceResponse());
3374
3375     if (newRequest.isNull())
3376         error = m_client->cancelledError(request);
3377     else
3378         error = ResourceError();
3379
3380     request = newRequest;
3381 }
3382
3383 void FrameLoader::loadedResourceFromMemoryCache(const ResourceRequest& request, const ResourceResponse& response, int length)
3384 {
3385     if (m_client->dispatchDidLoadResourceFromMemoryCache(m_documentLoader.get(), request, response, length))
3386         return;
3387
3388     unsigned long identifier;
3389     ResourceError error;
3390     ResourceRequest r(request);
3391     requestFromDelegate(r, identifier, error);
3392     sendRemainingDelegateMessages(identifier, response, length, error);
3393 }
3394
3395 void FrameLoader::applyUserAgent(ResourceRequest& request)
3396 {
3397     String userAgent = client()->userAgent(request.url());
3398     ASSERT(!userAgent.isNull());
3399     request.setHTTPUserAgent(userAgent);
3400 }
3401
3402 bool FrameLoader::canGoBackOrForward(int distance) const
3403 {
3404     if (distance == 0)
3405         return true;
3406     if (distance > 0 && distance <= m_frame->page()->backForwardList()->forwardListCount())
3407         return true;
3408     if (distance < 0 && -distance <= m_frame->page()->backForwardList()->backListCount())
3409         return true;
3410     return false;
3411 }
3412
3413 int FrameLoader::getHistoryLength()
3414 {
3415     return m_frame->page()->backForwardList()->backListCount() + 1;
3416 }
3417
3418 KURL FrameLoader::historyURL(int distance)
3419 {
3420     BackForwardList *list = m_frame->page()->backForwardList();
3421     HistoryItem* item = list->itemAtIndex(distance);
3422     if (!item) {
3423         if (distance > 0) {
3424             int forwardListCount = list->forwardListCount();
3425             if (forwardListCount > 0)
3426                 item = list->itemAtIndex(forwardListCount);
3427         } else {
3428             int backListCount = list->backListCount();
3429             if (backListCount > 0)
3430                 item = list->itemAtIndex(-backListCount);
3431         }
3432     }
3433     if (item)
3434         return item->url();
3435
3436     return KURL();
3437 }
3438
3439 void FrameLoader::addHistoryItemForFragmentScroll()
3440 {
3441     addBackForwardItemClippedAtTarget(false);
3442 }
3443
3444 bool FrameLoader::loadProvisionalItemFromPageCache()
3445 {
3446     if (!m_provisionalHistoryItem || !m_provisionalHistoryItem->hasPageCache())
3447         return false;
3448
3449     RefPtr<PageState> state = m_provisionalHistoryItem->pageCache()->pageState();
3450     if (!state)
3451         return false;
3452     
3453     provisionalDocumentLoader()->loadFromPageCache(m_provisionalHistoryItem->pageCache());
3454     return true;
3455 }
3456
3457 bool FrameLoader::createPageCache(HistoryItem* item)
3458 {
3459     RefPtr<PageState> pageState = PageState::create(m_frame->page());
3460     
3461     if (!pageState) {
3462         item->setHasPageCache(false);
3463         return false;
3464     }
3465     
3466     item->setHasPageCache(true);
3467     RefPtr<PageCache> pageCache = item->pageCache();
3468
3469     pageCache->setPageState(pageState.release());
3470     pageCache->setTimeStampToNow();
3471     pageCache->setDocumentLoader(documentLoader());
3472     m_client->saveDocumentViewToPageCache(pageCache.get());
3473
3474     return true;
3475 }
3476
3477 bool FrameLoader::shouldTreatURLAsSameAsCurrent(const KURL& URL) const
3478 {
3479     if (!m_currentHistoryItem)
3480         return false;
3481     return URL == m_currentHistoryItem->url() || URL == m_currentHistoryItem->originalURL();
3482 }
3483
3484 PassRefPtr<HistoryItem> FrameLoader::createHistoryItem(bool useOriginal)
3485 {
3486     DocumentLoader* docLoader = documentLoader();
3487     
3488     KURL unreachableURL = docLoader ? docLoader->unreachableURL() : KURL();
3489     
3490     KURL url;
3491     KURL originalURL;
3492
3493     if (!unreachableURL.isEmpty()) {
3494         url = unreachableURL;
3495         originalURL = unreachableURL;
3496     } else {
3497         originalURL = docLoader ? docLoader->originalURL() : KURL();
3498         if (useOriginal)
3499             url = originalURL;
3500         else if (docLoader)
3501             url = docLoader->requestURL();                
3502     }
3503
3504     LOG (History, "WebCoreHistory - Creating item for %s", url.url().ascii());
3505     
3506     // Frames that have never successfully loaded any content
3507     // may have no URL at all. Currently our history code can't
3508     // deal with such things, so we nip that in the bud here.
3509     // Later we may want to learn to live with nil for URL.
3510     // See bug 3368236 and related bugs for more information.
3511     if (url.isEmpty()) 
3512         url = KURL("about:blank");
3513     if (originalURL.isEmpty())
3514         originalURL = KURL("about:blank");
3515     
3516     RefPtr<HistoryItem> item = new HistoryItem(url, m_frame->tree()->name(), m_frame->tree()->parent() ? m_frame->tree()->parent()->tree()->name() : "", docLoader ? docLoader->title() : "");
3517     item->setOriginalURLString(originalURL.url());
3518     
3519     // Save form state if this is a POST
3520     if (docLoader) {
3521         if (useOriginal)
3522             item->setFormInfoFromRequest(docLoader->originalRequest());
3523         else
3524             item->setFormInfoFromRequest(docLoader->request());
3525     }
3526     
3527     // Set the item for which we will save document state
3528     m_previousHistoryItem = m_currentHistoryItem;
3529     m_currentHistoryItem = item;
3530     
3531     return item.release();
3532 }
3533
3534 void FrameLoader::addBackForwardItemClippedAtTarget(bool doClip)
3535 {
3536     if (!documentLoader()->urlForHistory().isEmpty()) {
3537         Frame* mainFrame = m_frame->page()->mainFrame();
3538         ASSERT(mainFrame);
3539         RefPtr<HistoryItem> item = mainFrame->loader()->createHistoryItemTree(m_frame, doClip);
3540         LOG(BackForward, "WebCoreBackForward - Adding backforward item %p for frame %s", item.get(), documentLoader()->URL().url().ascii());
3541         ASSERT(m_frame->page());
3542         m_frame->page()->backForwardList()->addItem(item);
3543     }
3544 }
3545
3546 PassRefPtr<HistoryItem> FrameLoader::createHistoryItemTree(Frame* targetFrame, bool clipAtTarget)
3547 {
3548     RefPtr<HistoryItem> bfItem = createHistoryItem(m_frame->tree()->parent() ? true : false);
3549     if (m_previousHistoryItem)
3550         saveScrollPositionAndViewStateToItem(m_previousHistoryItem.get());
3551     if (!(clipAtTarget && m_frame == targetFrame)) {
3552         // save frame state for items that aren't loading (khtml doesn't save those)
3553         saveDocumentState();
3554         for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
3555             bfItem->addChildItem(child->loader()->createHistoryItemTree(targetFrame, clipAtTarget));
3556     }
3557     if (m_frame == targetFrame)
3558         bfItem->setIsTargetItem(true);
3559     return bfItem;
3560 }
3561
3562 void FrameLoader::saveScrollPositionAndViewStateToItem(HistoryItem* item)
3563 {
3564     if (!item || !m_frame->view())
3565         return;
3566         
3567     item->setScrollPoint(IntPoint(m_frame->view()->contentsX(), m_frame->view()->contentsY()));
3568     // FIXME: It would be great to work out a way to put this code in WebCore instead of calling through to the client.
3569     m_client->saveViewStateToItem(item);
3570 }
3571
3572 /*
3573  There is a race condition between the layout and load completion that affects restoring the scroll position.
3574  We try to restore the scroll position at both the first layout and upon load completion.
3575  
3576  1) If first layout happens before the load completes, we want to restore the scroll position then so that the
3577  first time we draw the page is already scrolled to the right place, instead of starting at the top and later
3578  jumping down.  It is possible that the old scroll position is past the part of the doc laid out so far, in
3579  which case the restore silent fails and we will fix it in when we try to restore on doc completion.
3580  2) If the layout happens after the load completes, the attempt to restore at load completion time silently
3581  fails.  We then successfully restore it when the layout happens.
3582 */
3583 void FrameLoader::restoreScrollPositionAndViewState()
3584 {
3585     ASSERT(m_currentHistoryItem);
3586     
3587     // FIXME: As the ASSERT attests, it seems we should always have a currentItem here.
3588     // One counterexample is <rdar://problem/4917290>
3589     // For now, to cover this issue in release builds, there is no technical harm to returning
3590     // early and from a user standpoint - as in the above radar - the previous page load failed 
3591     // so there *is* no scroll or view state to restore!
3592     if (!m_currentHistoryItem)
3593         return;
3594     
3595     // FIXME: It would be great to work out a way to put this code in WebCore instead of calling through to the client.
3596     m_client->restoreViewState();
3597     
3598     if (m_frame->view()) {
3599         const IntPoint& scrollPoint = m_currentHistoryItem->scrollPoint();
3600         m_frame->view()->setContentsPos(scrollPoint.x(), scrollPoint.y());
3601     }
3602 }
3603
3604 void FrameLoader::purgePageCache()
3605 {
3606     // This method implements the rule for purging the page cache.
3607     if (!m_frame->page())
3608         return;
3609         
3610     BackForwardList* bfList = m_frame->page()->backForwardList();
3611     unsigned sizeLimit = bfList->pageCacheSize();
3612     unsigned pagesCached = 0;
3613
3614     HistoryItemVector items;
3615     bfList->backListWithLimit(INT_MAX, items);
3616     RefPtr<HistoryItem> oldestNonSnapbackItem;
3617     
3618     unsigned int i = 0;
3619     
3620     for (; i < items.size(); ++i) {
3621         if (items[i]->hasPageCache()) {
3622             if (!oldestNonSnapbackItem && !items[i]->alwaysAttemptToUsePageCache())
3623                 oldestNonSnapbackItem = items[i];
3624             pagesCached++;
3625         }
3626     }
3627     
3628     // Snapback items are never directly purged here.
3629     if (pagesCached >= sizeLimit && oldestNonSnapbackItem) {
3630         LOG(PageCache, "Purging back/forward cache, %s\n", oldestNonSnapbackItem->url().url().ascii());
3631         oldestNonSnapbackItem->setHasPageCache(false);
3632     }
3633 }
3634
3635 void FrameLoader::invalidateCurrentItemPageCache()
3636 {
3637     // When we are pre-commit, the currentItem is where the pageCache data resides    
3638     PageCache* pageCache = m_currentHistoryItem ? m_currentHistoryItem->pageCache() : 0;
3639     PageState* pageState = pageCache ? pageCache->pageState() : 0;
3640
3641     // FIXME: This is a grotesque hack to fix <rdar://problem/4059059> Crash in RenderFlow::detach
3642     // Somehow the PageState object is not properly updated, and is holding onto a stale document.
3643     // Both Xcode and FileMaker see this crash, Safari does not.
3644