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