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