WebCore:
[WebKit-https.git] / WebCore / loader / FrameLoader.cpp
1 /*
2  * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer. 
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution. 
13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission. 
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #include "config.h"
30 #include "FrameLoader.h"
31
32 #include "Cache.h"
33 #include "Chrome.h"
34 #include "DOMImplementation.h"
35 #include "DocLoader.h"
36 #include "Document.h"
37 #include "DocumentLoader.h"
38 #include "EditCommand.h"
39 #include "Editor.h"
40 #include "Element.h"
41 #include "EventNames.h"
42 #include "FloatRect.h"
43 #include "FormState.h"
44 #include "Frame.h"
45 #include "FrameLoadRequest.h"
46 #include "FrameLoaderClient.h"
47 #include "FramePrivate.h"
48 #include "FrameTree.h"
49 #include "FrameView.h"
50 #include "HTMLFormElement.h"
51 #include "HTMLNames.h"
52 #include "HTMLObjectElement.h"
53 #include "HTMLPlugInElement.h"
54 #include "IconDatabase.h"
55 #include "IconLoader.h"
56 #include "MainResourceLoader.h"
57 #include "Page.h"
58 #include "PageState.h"
59 #include "RenderPart.h"
60 #include "RenderWidget.h"
61 #include "ResourceRequest.h"
62 #include "SegmentedString.h"
63 #include "Settings.h"
64 #include "SystemTime.h"
65 #include "TextResourceDecoder.h"
66 #include "WindowFeatures.h"
67 #include "XMLTokenizer.h"
68 #include "kjs_binding.h"
69 #include "kjs_proxy.h"
70 #include "kjs_window.h"
71 #include "xmlhttprequest.h"
72 #include <kjs/JSLock.h>
73 #include <kjs/object.h>
74
75 #if PLATFORM(MAC)
76 #include "FrameMac.h"
77 #endif
78
79 using namespace KJS;
80
81 namespace WebCore {
82
83 using namespace HTMLNames;
84 using namespace EventNames;
85
86 struct FormSubmission {
87     const char* action;
88     String URL;
89     FormData data;
90     String target;
91     String contentType;
92     String boundary;
93     RefPtr<Event> event;
94
95     FormSubmission(const char* a, const String& u, const FormData& d, const String& t,
96             const String& ct, const String& b, PassRefPtr<Event> e)
97         : action(a)
98         , URL(u)
99         , data(d)
100         , target(t)
101         , contentType(ct)
102         , boundary(b)
103         , event(e)
104     {
105     }
106 };
107
108 struct ScheduledRedirection {
109     enum Type { redirection, locationChange, historyNavigation, locationChangeDuringLoad };
110     Type type;
111     double delay;
112     String URL;
113     String referrer;
114     int historySteps;
115     bool lockHistory;
116     bool wasUserGesture;
117
118     ScheduledRedirection(double redirectDelay, const String& redirectURL, bool redirectLockHistory)
119         : type(redirection)
120         , delay(redirectDelay)
121         , URL(redirectURL)
122         , historySteps(0)
123         , lockHistory(redirectLockHistory)
124         , wasUserGesture(false)
125     {
126     }
127
128     ScheduledRedirection(Type locationChangeType,
129             const String& locationChangeURL, const String& locationChangeReferrer,
130             bool locationChangeLockHistory, bool locationChangeWasUserGesture)
131         : type(locationChangeType)
132         , delay(0)
133         , URL(locationChangeURL)
134         , referrer(locationChangeReferrer)
135         , historySteps(0)
136         , lockHistory(locationChangeLockHistory)
137         , wasUserGesture(locationChangeWasUserGesture)
138     {
139     }
140
141     explicit ScheduledRedirection(int historyNavigationSteps)
142         : type(historyNavigation)
143         , delay(0)
144         , historySteps(historyNavigationSteps)
145         , lockHistory(false)
146         , wasUserGesture(false)
147     {
148     }
149 };
150
151 static double storedTimeOfLastCompletedLoad;
152
153 static void cancelAll(const ResourceLoaderSet& loaders)
154 {
155     const ResourceLoaderSet copy = loaders;
156     ResourceLoaderSet::const_iterator end = copy.end();
157     for (ResourceLoaderSet::const_iterator it = copy.begin(); it != end; ++it)
158         (*it)->cancel();
159 }
160
161 static bool getString(JSValue* result, String& string)
162 {
163     if (!result)
164         return false;
165     JSLock lock;
166     UString ustring;
167     if (!result->getString(ustring))
168         return false;
169     string = ustring;
170     return true;
171 }
172
173 bool isBackForwardLoadType(FrameLoadType type)
174 {
175     switch (type) {
176         case FrameLoadTypeStandard:
177         case FrameLoadTypeReload:
178         case FrameLoadTypeReloadAllowingStaleData:
179         case FrameLoadTypeSame:
180         case FrameLoadTypeInternal:
181         case FrameLoadTypeReplace:
182             return false;
183         case FrameLoadTypeBack:
184         case FrameLoadTypeForward:
185         case FrameLoadTypeIndexedBackForward:
186             return true;
187     }
188     ASSERT_NOT_REACHED();
189     return false;
190 }
191
192 static int numRequests(Document* document)
193 {
194     if (document)
195         return cache()->loader()->numRequests(document->docLoader());
196     return 0;
197 }
198
199 FrameLoader::FrameLoader(Frame* frame)
200     : m_frame(frame)
201     , m_client(0)
202     , m_state(FrameStateCommittedPage)
203     , m_loadType(FrameLoadTypeStandard)
204     , m_policyLoadType(FrameLoadTypeStandard)
205     , m_delegateIsHandlingProvisionalLoadError(false)
206     , m_delegateIsDecidingNavigationPolicy(false)
207     , m_delegateIsHandlingUnimplementablePolicy(false)
208     , m_firstLayoutDone(false)
209     , m_quickRedirectComing(false)
210     , m_sentRedirectNotification(false)
211     , m_inStopAllLoaders(false)
212     , m_cachePolicy(CachePolicyVerify)
213     , m_isExecutingJavaScriptFormAction(false)
214     , m_isRunningScript(false)
215     , m_wasLoadEventEmitted(false)
216     , m_wasUnloadEventEmitted(false)
217     , m_isComplete(false)
218     , m_isLoadingMainResource(false)
219     , m_cancellingWithLoadInProgress(false)
220     , m_needsClear(false)
221     , m_receivedData(false)
222     , m_encodingWasChosenByUser(false)
223     , m_containsPlugIns(false)
224     , m_redirectionTimer(this, &FrameLoader::redirectionTimerFired)
225     , m_opener(0)
226     , m_openedByJavaScript(false)
227 {
228 }
229
230 FrameLoader::~FrameLoader()
231 {
232     setOpener(0);
233
234     HashSet<Frame*>::iterator end = m_openedFrames.end();
235     for (HashSet<Frame*>::iterator it = m_openedFrames.begin(); it != end; ++it)
236         (*it)->loader()->m_opener = 0;
237 }
238
239 static void setAllDefersLoading(const ResourceLoaderSet& loaders, bool defers)
240 {
241     const ResourceLoaderSet copy = loaders;
242     ResourceLoaderSet::const_iterator end = copy.end();
243     for (ResourceLoaderSet::const_iterator it = copy.begin(); it != end; ++it)
244         (*it)->setDefersLoading(defers);
245 }
246
247 void FrameLoader::setDefersLoading(bool defers)
248 {
249     if (m_mainResourceLoader)
250         m_mainResourceLoader->setDefersLoading(defers);
251     setAllDefersLoading(m_subresourceLoaders, defers);
252     setAllDefersLoading(m_plugInStreamLoaders, defers);
253     m_client->setDefersLoading(defers);
254 }
255
256 Frame* FrameLoader::createWindow(const FrameLoadRequest& request, const WindowFeatures& features)
257
258     ASSERT(!features.dialog || request.frameName().isEmpty());
259
260     if (!request.frameName().isEmpty())
261         if (Frame* frame = m_frame->tree()->find(request.frameName())) {
262 #if PLATFORM(MAC)
263             if (!request.resourceRequest().url().isEmpty())
264                 frame->loader()->load(request, true, 0, 0, HashMap<String, String>());
265 #endif
266             frame->page()->chrome()->focus();
267             return frame;
268         }
269
270     // FIXME: Setting the referrer should be the caller's responsibility.
271     FrameLoadRequest requestWithReferrer = request;
272     requestWithReferrer.resourceRequest().setHTTPReferrer(m_outgoingReferrer);
273     
274     Page* page;
275     if (features.dialog)
276         page = m_frame->page()->chrome()->createModalDialog(requestWithReferrer);
277     else
278         page = m_frame->page()->chrome()->createWindow(requestWithReferrer);
279     if (!page)
280         return 0;
281
282     Frame* frame = page->mainFrame();
283     frame->tree()->setName(request.frameName());
284
285     page->chrome()->setToolbarsVisible(features.toolBarVisible || features.locationBarVisible);
286     page->chrome()->setStatusbarVisible(features.statusBarVisible);
287     page->chrome()->setScrollbarsVisible(features.scrollbarsVisible);
288     page->chrome()->setMenubarVisible(features.menuBarVisible);
289     page->chrome()->setResizable(features.resizable);
290
291     // 'x' and 'y' specify the location of the window, while 'width' and 'height' 
292     // specify the size of the page. We can only resize the window, so 
293     // adjust for the difference between the window size and the page size.
294
295     FloatRect windowRect = page->chrome()->windowRect();
296     FloatSize pageSize = page->chrome()->pageRect().size();
297     if (features.xSet)
298         windowRect.setX(features.x);
299     if (features.ySet)
300         windowRect.setY(features.y);
301     if (features.widthSet)
302         windowRect.setWidth(features.width + (windowRect.width() - pageSize.width()));
303     if (features.heightSet)
304         windowRect.setHeight(features.height + (windowRect.height() - pageSize.height()));
305     page->chrome()->setWindowRect(windowRect);
306
307     page->chrome()->show();
308
309     return frame;
310 }
311
312 void FrameLoader::changeLocation(const String& URL, const String& referrer, bool lockHistory, bool userGesture)
313 {
314     if (URL.find("javascript:", 0, false) == 0) {
315         String script = KURL::decode_string(URL.substring(strlen("javascript:")).deprecatedString());
316         JSValue* result = executeScript(0, script, userGesture);
317         String scriptResult;
318         if (getString(result, scriptResult)) {
319             begin(m_URL);
320             write(scriptResult);
321             end();
322         }
323         return;
324     }
325
326     ResourceRequestCachePolicy policy = (m_cachePolicy == CachePolicyReload) || (m_cachePolicy == CachePolicyRefresh)
327         ? ReloadIgnoringCacheData : UseProtocolCachePolicy;
328     ResourceRequest request(completeURL(URL), referrer, policy);
329     
330     urlSelected(request, "_self", 0, lockHistory);
331 }
332
333 void FrameLoader::urlSelected(const ResourceRequest& request, const String& _target, Event* triggeringEvent, bool lockHistory)
334 {
335     String target = _target;
336     if (target.isEmpty() && m_frame->document())
337         target = m_frame->document()->baseTarget();
338
339     const KURL& url = request.url();
340     if (url.url().startsWith("javascript:", false)) {
341         executeScript(0, KURL::decode_string(url.url().mid(strlen("javascript:"))), true);
342         return;
343     }
344
345     if (!url.isValid())
346         return;
347
348     FrameLoadRequest frameRequest(request, target);
349
350     if (frameRequest.resourceRequest().httpReferrer().isEmpty())
351         frameRequest.resourceRequest().setHTTPReferrer(m_outgoingReferrer);
352
353     urlSelected(frameRequest, triggeringEvent);
354 }
355
356 bool FrameLoader::requestFrame(Element* ownerElement, const String& urlString, const AtomicString& frameName)
357 {
358     // Support for <frame src="javascript:string">
359     KURL scriptURL;
360     KURL url;
361     if (urlString.startsWith("javascript:", false)) {
362         scriptURL = urlString.deprecatedString();
363         url = "about:blank";
364     } else
365         url = completeURL(urlString);
366
367     Frame* frame = m_frame->tree()->child(frameName);
368     if (frame) {
369         ResourceRequestCachePolicy policy = (m_cachePolicy == CachePolicyReload) || (m_cachePolicy == CachePolicyRefresh)
370             ? ReloadIgnoringCacheData : UseProtocolCachePolicy;
371         frame->loader()->urlSelected(ResourceRequest(url, m_outgoingReferrer, policy), 0);
372     } else
373         frame = loadSubframe(ownerElement, url, frameName, m_outgoingReferrer);
374     
375     if (!frame)
376         return false;
377
378     if (!scriptURL.isEmpty())
379         frame->loader()->replaceContentsWithScriptResult(scriptURL);
380
381     return true;
382 }
383
384 Frame* FrameLoader::loadSubframe(Element* ownerElement, const KURL& url, const String& name, const String& referrer)
385 {
386     Frame* frame = createFrame(url, name, ownerElement, referrer);
387     if (!frame)  {
388         checkEmitLoadEvent();
389         return 0;
390     }
391     
392     frame->loader()->m_isComplete = false;
393     
394     if (ownerElement->renderer() && frame->view())
395         static_cast<RenderWidget*>(ownerElement->renderer())->setWidget(frame->view());
396     
397     checkEmitLoadEvent();
398     
399     // In these cases, the synchronous load would have finished
400     // before we could connect the signals, so make sure to send the 
401     // completed() signal for the child by hand
402     // FIXME: In this case the Frame will have finished loading before 
403     // it's being added to the child list. It would be a good idea to
404     // create the child first, then invoke the loader separately.
405     if (url.isEmpty() || url == "about:blank") {
406         frame->loader()->completed();
407         frame->loader()->checkCompleted();
408     }
409
410     return frame;
411 }
412
413 void FrameLoader::submitFormAgain()
414 {
415     if (m_isRunningScript)
416         return;
417     OwnPtr<FormSubmission> form(m_deferredFormSubmission.release());
418     if (form)
419         submitForm(form->action, form->URL, form->data, form->target,
420             form->contentType, form->boundary, form->event.get());
421 }
422
423 void FrameLoader::submitForm(const char* action, const String& url, const FormData& formData,
424     const String& target, const String& contentType, const String& boundary, Event* event)
425 {
426     KURL u = completeURL(url.isNull() ? "" : url);
427     if (!u.isValid())
428         return;
429
430     DeprecatedString urlString = u.url();
431     if (urlString.startsWith("javascript:", false)) {
432         m_isExecutingJavaScriptFormAction = true;
433         executeScript(0, KURL::decode_string(urlString.mid(strlen("javascript:"))));
434         m_isExecutingJavaScriptFormAction = false;
435         return;
436     }
437
438     if (m_isRunningScript) {
439         if (m_deferredFormSubmission)
440             return;
441         m_deferredFormSubmission.set(new FormSubmission(action, url, formData, target,
442             contentType, boundary, event));
443         return;
444     }
445
446     FrameLoadRequest frameRequest;
447
448     if (!m_outgoingReferrer.isEmpty())
449         frameRequest.resourceRequest().setHTTPReferrer(m_outgoingReferrer);
450
451     frameRequest.setFrameName(target.isEmpty() ? m_frame->document()->baseTarget() : target);
452
453     // Handle mailto: forms
454     bool mailtoForm = u.protocol() == "mailto";
455     if (mailtoForm) {
456         // Append body=
457         DeprecatedString encodedBody;
458         if (equalIgnoringCase(contentType, "multipart/form-data"))
459             // FIXME: is this correct? I suspect not, but what site can we test this on?
460             encodedBody = KURL::encode_string(formData.flattenToString().deprecatedString());
461         else if (equalIgnoringCase(contentType, "text/plain")) {
462             // Convention seems to be to decode, and s/&/\n/
463             encodedBody = formData.flattenToString().deprecatedString();
464             encodedBody.replace('&', '\n');
465             encodedBody.replace('+', ' ');
466             encodedBody = KURL::decode_string(encodedBody); // Decode the rest of it
467             encodedBody = KURL::encode_string(encodedBody); // Recode for the URL
468         } else
469             encodedBody = KURL::encode_string(formData.flattenToString().deprecatedString());
470
471         DeprecatedString query = u.query();
472         if (!query.isEmpty())
473             query += '&';
474         query += "body=";
475         query += encodedBody;
476         u.setQuery(query);
477     }
478
479     if (strcmp(action, "GET") == 0) {
480         if (!mailtoForm)
481             u.setQuery(formData.flattenToString().deprecatedString());
482     } else {
483         frameRequest.resourceRequest().setHTTPBody(formData);
484         frameRequest.resourceRequest().setHTTPMethod("POST");
485
486         // construct some user headers if necessary
487         if (contentType.isNull() || contentType == "application/x-www-form-urlencoded")
488             frameRequest.resourceRequest().setHTTPContentType(contentType);
489         else // contentType must be "multipart/form-data"
490             frameRequest.resourceRequest().setHTTPContentType(contentType + "; boundary=" + boundary);
491     }
492
493     frameRequest.resourceRequest().setURL(u);
494
495     submitForm(frameRequest, event);
496 }
497
498 void FrameLoader::stopLoading(bool sendUnload)
499 {
500     if (m_frame->document() && m_frame->document()->tokenizer())
501         m_frame->document()->tokenizer()->stopParsing();
502   
503     m_responseRefreshHeader = String();
504     m_responseModifiedHeader = String();
505
506     if (sendUnload) {
507         if (m_frame->document()) {
508             if (m_wasLoadEventEmitted && !m_wasUnloadEventEmitted) {
509                 Node* currentFocusNode = m_frame->document()->focusNode();
510                 if (currentFocusNode)
511                     currentFocusNode->aboutToUnload();
512                 m_frame->document()->dispatchWindowEvent(unloadEvent, false, false);
513                 if (m_frame->document())
514                     m_frame->document()->updateRendering();
515                 m_wasUnloadEventEmitted = true;
516             }
517         }
518         if (m_frame->document() && !m_frame->document()->inPageCache())
519             m_frame->document()->removeAllEventListenersFromAllNodes();
520     }
521
522     m_isComplete = true; // to avoid calling completed() in finishedParsing() (David)
523     m_isLoadingMainResource = false;
524     m_wasLoadEventEmitted = true; // don't want that one either
525     m_cachePolicy = CachePolicyVerify; // Why here?
526
527     if (m_frame->document() && m_frame->document()->parsing()) {
528         finishedParsing();
529         m_frame->document()->setParsing(false);
530     }
531   
532     m_workingURL = KURL();
533
534     if (Document* doc = m_frame->document()) {
535         if (DocLoader* docLoader = doc->docLoader())
536             cache()->loader()->cancelRequests(docLoader);
537         XMLHttpRequest::cancelRequests(doc);
538     }
539
540     // tell all subframes to stop as well
541     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
542         child->loader()->stopLoading(sendUnload);
543
544     cancelRedirection();
545 }
546
547 void FrameLoader::stop()
548 {
549     // http://bugs.webkit.org/show_bug.cgi?id=10854
550     // The frame's last ref may be removed and it will be deleted by checkCompleted().
551     RefPtr<Frame> protector(m_frame);
552     
553     if (m_frame->document()) {
554         if (m_frame->document()->tokenizer())
555             m_frame->document()->tokenizer()->stopParsing();
556         m_frame->document()->finishParsing();
557     } else
558         // WebKit partially uses WebCore when loading non-HTML docs.  In these cases doc==nil, but
559         // WebCore is enough involved that we need to checkCompleted() in order for m_bComplete to
560         // become true. An example is when a subframe is a pure text doc, and that subframe is the
561         // last one to complete.
562         checkCompleted();
563     if (m_iconLoader)
564         m_iconLoader->stopLoading();
565 }
566
567 bool FrameLoader::closeURL()
568 {
569     saveDocumentState();
570     stopLoading(true);
571     m_frame->clearUndoRedoOperations();
572     return true;
573 }
574
575 void FrameLoader::cancelRedirection(bool cancelWithLoadInProgress)
576 {
577     m_cancellingWithLoadInProgress = cancelWithLoadInProgress;
578
579     stopRedirectionTimer();
580
581     m_scheduledRedirection.clear();
582 }
583
584 KURL FrameLoader::iconURL()
585 {
586     // If this isn't a top level frame, return nothing
587     if (m_frame->tree() && m_frame->tree()->parent())
588         return "";
589         
590     // If we have an iconURL from a Link element, return that
591     if (m_frame->document() && !m_frame->document()->iconURL().isEmpty())
592         return m_frame->document()->iconURL().deprecatedString();
593         
594     // Don't return a favicon iconURL unless we're http or https
595     if (m_URL.protocol() != "http" && m_URL.protocol() != "https")
596         return "";
597         
598     KURL url;
599     url.setProtocol(m_URL.protocol());
600     url.setHost(m_URL.host());
601     url.setPath("/favicon.ico");
602     return url;
603 }
604
605 bool FrameLoader::didOpenURL(const KURL& url)
606 {
607     if (m_scheduledRedirection && m_scheduledRedirection->type == ScheduledRedirection::locationChangeDuringLoad)
608         // A redirect was scheduled before the document was created.
609         // This can happen when one frame changes another frame's location.
610         return false;
611
612     cancelRedirection();
613     m_frame->editor()->setLastEditCommand(0);
614     closeURL();
615
616     m_isComplete = false;
617     m_isLoadingMainResource = true;
618     m_wasLoadEventEmitted = false;
619
620     m_frame->d->m_kjsStatusBarText = String();
621     m_frame->d->m_kjsDefaultStatusBarText = String();
622
623     m_frame->d->m_bJScriptEnabled = m_frame->settings()->isJavaScriptEnabled();
624     m_frame->d->m_bJavaEnabled = m_frame->settings()->isJavaEnabled();
625     m_frame->d->m_bPluginsEnabled = m_frame->settings()->isPluginsEnabled();
626
627     m_URL = url;
628     if (m_URL.protocol().startsWith("http") && !m_URL.host().isEmpty() && m_URL.path().isEmpty())
629         m_URL.setPath("/");
630     m_workingURL = m_URL;
631
632     started();
633
634     return true;
635 }
636
637 void FrameLoader::didExplicitOpen()
638 {
639     m_isComplete = false;
640     m_wasLoadEventEmitted = false;
641
642     // Prevent window.open(url) -- eg window.open("about:blank") -- from blowing away results
643     // from a subsequent window.document.open / window.document.write call. 
644     // Cancelling redirection here works for all cases because document.open 
645     // implicitly precedes document.write.
646     cancelRedirection(); 
647     m_URL = m_frame->document()->URL();
648 }
649
650 void FrameLoader::replaceContentsWithScriptResult(const KURL& url)
651 {
652     JSValue* result = executeScript(0, KURL::decode_string(url.url().mid(strlen("javascript:"))));
653     String scriptResult;
654     if (!getString(result, scriptResult))
655         return;
656     begin();
657     write(scriptResult);
658     end();
659 }
660
661 JSValue* FrameLoader::executeScript(Node* node, const String& script, bool forceUserGesture)
662 {
663     return executeScript(forceUserGesture ? String() : String(m_URL.url()), 0, node, script);
664 }
665
666 JSValue* FrameLoader::executeScript(const String& URL, int baseLine, Node* node, const String& script)
667 {
668     KJSProxy* proxy = m_frame->scriptProxy();
669     if (!proxy)
670         return 0;
671
672     bool wasRunningScript = m_isRunningScript;
673     m_isRunningScript = true;
674
675     JSValue* result = proxy->evaluate(URL, baseLine, script, node);
676
677     if (!wasRunningScript) {
678         m_isRunningScript = false;
679         submitFormAgain();
680         Document::updateDocumentsRendering();
681     }
682
683     return result;
684 }
685
686 void FrameLoader::cancelAndClear()
687 {
688     cancelRedirection();
689
690     if (!m_isComplete)
691         closeURL();
692
693     clear(false);
694 }
695
696 void FrameLoader::clear(bool clearWindowProperties)
697 {
698     // FIXME: Commenting out the below line causes <http://bugs.webkit.org/show_bug.cgi?id=11212>, but putting it
699     // back causes a measurable performance regression which we will need to fix to restore the correct behavior
700     // urlsBridgeKnowsAbout.clear();
701
702 #if PLATFORM(MAC)
703     Mac(m_frame)->setMarkedTextRange(0, nil, nil);
704 #endif
705
706     if (!m_needsClear)
707         return;
708     m_needsClear = false;
709     m_frame->d->m_mousePressNode = 0;
710
711 #if !PLATFORM(MAC)
712     // FIXME: Remove this after making other platforms do loading more like Mac.
713     detachChildren();
714 #endif
715
716     if (m_frame->document()) {
717         m_frame->document()->cancelParsing();
718         m_frame->document()->detach();
719     }
720
721     // Do this after detaching the document so that the unload event works.
722     if (clearWindowProperties && m_frame->scriptProxy())
723         m_frame->scriptProxy()->clear();
724
725     if (m_frame->view())
726         m_frame->view()->clear();
727
728     // Do not drop the document before the script proxy and view are cleared, as some destructors
729     // might still try to access the document.
730     m_frame->d->m_doc = 0;
731     m_decoder = 0;
732
733     m_containsPlugIns = false;
734     m_frame->cleanupPluginObjects();
735   
736     m_redirectionTimer.stop();
737     m_scheduledRedirection.clear();
738
739     m_receivedData = false;
740
741     m_frame->d->m_bMousePressed = false;
742
743     if (!m_encodingWasChosenByUser)
744         m_encoding = String();
745 }
746
747 void FrameLoader::receivedFirstData()
748 {
749     begin(m_workingURL);
750
751     m_frame->document()->docLoader()->setCachePolicy(m_cachePolicy);
752     m_workingURL = KURL();
753
754     const String& refresh = m_responseRefreshHeader;
755     if (refresh.isEmpty())
756         return;
757
758     double delay;
759     String URL;
760
761     int pos = refresh.find(';');
762     if (pos == -1)
763         pos = refresh.find(',');
764     if (pos == -1) {
765         delay = refresh.stripWhiteSpace().toDouble();
766         URL = m_URL.url();
767     } else {
768         int endPos = refresh.length();
769         delay = refresh.left(pos).stripWhiteSpace().toDouble();
770         while (refresh[++pos] == ' ')
771             ;
772         if (refresh.find("url", pos, false) == pos) {
773             pos += 3;
774             while (refresh[pos] == ' ' || refresh[pos] == '=')
775                 pos++;
776             if (refresh[pos] == '"') {
777                 pos++;
778                 int index = endPos - 1;
779                 while (index > pos) {
780                     if (refresh[index] == '"')
781                         break;
782                     index--;
783                 }
784                 if (index > pos)
785                     endPos = index;
786             }
787         }
788         URL = m_frame->document()->completeURL(refresh.substring(pos, endPos - pos));
789     }
790
791     // We want a new history item if the refresh timeout > 1 second
792     scheduleRedirection(delay, URL, delay <= 1);
793 }
794
795 const String& FrameLoader::responseMIMEType() const
796 {
797     return m_responseMIMEType;
798 }
799
800 void FrameLoader::setResponseMIMEType(const String& type)
801 {
802     m_responseMIMEType = type;
803 }
804
805 void FrameLoader::begin()
806 {
807     begin(KURL());
808 }
809
810 void FrameLoader::begin(const KURL& url)
811 {
812     if (m_workingURL.isEmpty())
813         createEmptyDocument(); // Creates an empty document if we don't have one already
814
815     clear();
816     partClearedInBegin();
817
818     m_needsClear = true;
819     m_isComplete = false;
820     m_wasLoadEventEmitted = false;
821     m_isLoadingMainResource = true;
822
823     KURL ref(url);
824     ref.setUser(DeprecatedString());
825     ref.setPass(DeprecatedString());
826     ref.setRef(DeprecatedString());
827     m_outgoingReferrer = ref.url();
828     m_URL = url;
829     KURL baseurl;
830
831     if (!m_URL.isEmpty())
832         baseurl = m_URL;
833
834     RefPtr<Document> document = DOMImplementation::instance()->
835         createDocument(m_responseMIMEType, m_frame->view(), m_frame->inViewSourceMode());
836     m_frame->d->m_doc = document;
837
838     if (!document->attached())
839         document->attach();
840     document->setURL(m_URL.url());
841     // We prefer m_baseURL over m_URL because m_URL changes when we are
842     // about to load a new page.
843     document->setBaseURL(baseurl.url());
844     if (m_decoder)
845         document->setDecoder(m_decoder.get());
846
847     updatePolicyBaseURL();
848
849     document->docLoader()->setAutoLoadImages(m_frame->settings()->autoLoadImages());
850
851     const KURL& userStyleSheet = m_frame->settings()->userStyleSheetLocation();
852     if (!userStyleSheet.isEmpty())
853         m_frame->setUserStyleSheetLocation(KURL(userStyleSheet));
854
855     restoreDocumentState();
856
857     document->implicitOpen();
858
859     if (m_frame->view())
860         m_frame->view()->resizeContents(0, 0);
861 }
862
863 void FrameLoader::write(const char* str, int len)
864 {
865     if (len == 0)
866         return;
867     
868     if (len == -1)
869         len = strlen(str);
870
871     Tokenizer* tokenizer = m_frame->document()->tokenizer();
872     if (tokenizer && tokenizer->wantsRawData()) {
873         tokenizer->writeRawData(str, len);
874         return;
875     }
876     
877     if (!m_decoder) {
878         m_decoder = new TextResourceDecoder(m_responseMIMEType, m_frame->settings()->encoding());
879         if (!m_encoding.isNull())
880             m_decoder->setEncoding(m_encoding,
881                 m_encodingWasChosenByUser ? TextResourceDecoder::UserChosenEncoding : TextResourceDecoder::EncodingFromHTTPHeader);
882         if (m_frame->document())
883             m_frame->document()->setDecoder(m_decoder.get());
884     }
885
886     String decoded = m_decoder->decode(str, len);
887     if (decoded.isEmpty())
888         return;
889
890     if (!m_receivedData) {
891         m_receivedData = true;
892         m_frame->document()->determineParseMode(decoded);
893         if (m_decoder->encoding().usesVisualOrdering())
894             m_frame->document()->setVisuallyOrdered();
895         m_frame->document()->recalcStyle(Node::Force);
896     }
897
898     if (tokenizer) {
899         ASSERT(!tokenizer->wantsRawData());
900         tokenizer->write(decoded, true);
901     }
902 }
903
904 void FrameLoader::write(const String& str)
905 {
906     if (str.isNull())
907         return;
908
909     if (!m_receivedData) {
910         m_receivedData = true;
911         m_frame->document()->setParseMode(Document::Strict);
912     }
913
914     if (Tokenizer* tokenizer = m_frame->document()->tokenizer())
915         tokenizer->write(str, true);
916 }
917
918 void FrameLoader::end()
919 {
920     m_isLoadingMainResource = false;
921     endIfNotLoading();
922 }
923
924 void FrameLoader::endIfNotLoading()
925 {
926     // http://bugs.webkit.org/show_bug.cgi?id=10854
927     // The frame's last ref may be removed and it can be deleted by checkCompleted(), 
928     // so we'll add a protective refcount
929     RefPtr<Frame> protector(m_frame);
930
931     if (m_isLoadingMainResource)
932         return;
933
934     // make sure nothing's left in there
935     if (m_frame->document()) {
936         if (m_decoder) {
937             String decoded = m_decoder->flush();
938             if (!m_receivedData) {
939                 m_receivedData = true;
940                 m_frame->document()->determineParseMode(decoded);
941             }
942             write(decoded);
943         }
944         m_frame->document()->finishParsing();
945     } else
946         // WebKit partially uses WebCore when loading non-HTML docs.  In these cases doc==nil, but
947         // WebCore is enough involved that we need to checkCompleted() in order for m_bComplete to
948         // become true.  An example is when a subframe is a pure text doc, and that subframe is the
949         // last one to complete.
950         checkCompleted();
951
952     startIconLoader();
953 }
954
955 void FrameLoader::startIconLoader()
956 {
957     // FIXME: We kick off the icon loader when the frame is done receiving its main resource.
958     // But we should instead do it when we're done parsing the head element.
959     if (!isLoadingMainFrame())
960         return;
961
962     IconDatabase* iconDB = IconDatabase::sharedIconDatabase();
963     if (!iconDB)
964         return;
965     if (!iconDB->enabled())
966         return;
967
968     KURL url(iconURL());
969     String urlString(url.url());
970     if (urlString.isEmpty())
971         return;
972
973     // If we already have an unexpired icon, we won't kick off a load but we *will* map the appropriate URLs to it
974     if (iconDB->hasEntryForIconURL(urlString) && loadType() != FrameLoadTypeReload && !iconDB->isIconExpiredForIconURL(urlString)) {
975         commitIconURLToIconDatabase(url);
976         return;
977     }
978
979     if (!m_iconLoader)
980         m_iconLoader.set(IconLoader::create(m_frame).release());
981     m_iconLoader->startLoading();
982 }
983
984 void FrameLoader::commitIconURLToIconDatabase(const KURL& icon)
985 {
986     IconDatabase* iconDB = IconDatabase::sharedIconDatabase();
987     ASSERT(iconDB);
988     iconDB->setIconURLForPageURL(icon.url(), m_URL.url());
989     iconDB->setIconURLForPageURL(icon.url(), originalRequestURL().url());
990 }
991
992 void FrameLoader::gotoAnchor()
993 {
994     // If our URL has no ref, then we have no place we need to jump to.
995     if (!m_URL.hasRef())
996         return;
997
998     DeprecatedString ref = m_URL.encodedHtmlRef();
999     if (!gotoAnchor(ref)) {
1000         // Can't use htmlRef() here because it doesn't know which encoding to use to decode.
1001         // Decoding here has to match encoding in completeURL, which means it has to use the
1002         // page's encoding rather than UTF-8.
1003         if (m_decoder)
1004             gotoAnchor(KURL::decode_string(ref, m_decoder->encoding()));
1005     }
1006 }
1007
1008 void FrameLoader::finishedParsing()
1009 {
1010     // This can be called from the Frame's destructor, in which case we shouldn't protect ourselves
1011     // because doing so will cause us to re-enter the destructor when protector goes out of scope.
1012     RefPtr<Frame> protector = m_frame->refCount() > 0 ? m_frame : 0;
1013
1014     checkCompleted();
1015
1016     if (!m_frame->view())
1017         return; // We are being destroyed by something checkCompleted called.
1018
1019     // Check if the scrollbars are really needed for the content.
1020     // If not, remove them, relayout, and repaint.
1021     m_frame->view()->restoreScrollbar();
1022
1023     gotoAnchor();
1024 }
1025
1026 void FrameLoader::loadDone()
1027 {
1028     if (m_frame->document())
1029         checkCompleted();
1030 }
1031
1032 void FrameLoader::checkCompleted()
1033 {
1034     // Any frame that hasn't completed yet?
1035     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
1036         if (!child->loader()->m_isComplete)
1037             return;
1038
1039     // Have we completed before?
1040     if (m_isComplete)
1041         return;
1042
1043     // Are we still parsing?
1044     if (m_frame->document() && m_frame->document()->parsing())
1045         return;
1046
1047     // Still waiting for images/scripts?
1048     if (m_frame->document() && m_frame->document()->docLoader())
1049         if (cache()->loader()->numRequests(m_frame->document()->docLoader()))
1050             return;
1051
1052     // OK, completed.
1053     m_isComplete = true;
1054
1055     checkEmitLoadEvent(); // if we didn't do it before
1056
1057     // Do not start a redirection timer for subframes here.
1058     // That is deferred until the parent is completed.
1059     if (m_scheduledRedirection && !m_frame->tree()->parent())
1060         startRedirectionTimer();
1061
1062     completed();
1063 }
1064
1065 void FrameLoader::checkEmitLoadEvent()
1066 {
1067     if (m_wasLoadEventEmitted || !m_frame->document() || m_frame->document()->parsing())
1068         return;
1069
1070     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
1071         if (!child->loader()->m_isComplete) // still got a frame running -> too early
1072             return;
1073
1074     // All frames completed -> set their domain to the frameset's domain
1075     // This must only be done when loading the frameset initially (#22039),
1076     // not when following a link in a frame (#44162).
1077     if (m_frame->document()) {
1078         String domain = m_frame->document()->domain();
1079         for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
1080             if (child->document())
1081                 child->document()->setDomain(domain);
1082     }
1083
1084     m_wasLoadEventEmitted = true;
1085     m_wasUnloadEventEmitted = false;
1086     if (m_frame->document())
1087         m_frame->document()->implicitClose();
1088 }
1089
1090 KURL FrameLoader::baseURL() const
1091 {
1092     if (!m_frame->document())
1093         return KURL();
1094     return m_frame->document()->baseURL();
1095 }
1096
1097 String FrameLoader::baseTarget() const
1098 {
1099     if (!m_frame->document())
1100         return String();
1101     return m_frame->document()->baseTarget();
1102 }
1103
1104 KURL FrameLoader::completeURL(const String& url)
1105 {
1106     if (!m_frame->document())
1107         return url.deprecatedString();
1108     return m_frame->document()->completeURL(url).deprecatedString();
1109 }
1110
1111 void FrameLoader::scheduleRedirection(double delay, const String& url, bool doLockHistory)
1112 {
1113     if (delay < 0 || delay > INT_MAX / 1000)
1114         return;
1115     if (!m_scheduledRedirection || delay <= m_scheduledRedirection->delay)
1116         scheduleRedirection(new ScheduledRedirection(delay, url, doLockHistory));
1117 }
1118
1119 void FrameLoader::scheduleLocationChange(const String& url, const String& referrer, bool lockHistory, bool wasUserGesture)
1120 {    
1121     // If the URL we're going to navigate to is the same as the current one, except for the
1122     // fragment part, we don't need to schedule the location change.
1123     KURL u(url.deprecatedString());
1124     if (u.hasRef() && equalIgnoringRef(m_URL, u)) {
1125         changeLocation(url, referrer, lockHistory, wasUserGesture);
1126         return;
1127     }
1128
1129     // Handle a location change of a page with no document as a special case.
1130     // This may happen when a frame changes the location of another frame.
1131     bool duringLoad = !m_frame->document();
1132
1133     // If a redirect was scheduled during a load, then stop the current load.
1134     // Otherwise when the current load transitions from a provisional to a 
1135     // committed state, pending redirects may be cancelled. 
1136     if (duringLoad)
1137         stopLoading(true);   
1138
1139     ScheduledRedirection::Type type = duringLoad
1140         ? ScheduledRedirection::locationChangeDuringLoad : ScheduledRedirection::locationChange;
1141     scheduleRedirection(new ScheduledRedirection(type, url, referrer, lockHistory, wasUserGesture));
1142 }
1143
1144 void FrameLoader::scheduleRefresh(bool wasUserGesture)
1145 {
1146     // Handle a location change of a page with no document as a special case.
1147     // This may happen when a frame requests a refresh of another frame.
1148     bool duringLoad = !m_frame->document();
1149     
1150     // If a refresh was scheduled during a load, then stop the current load.
1151     // Otherwise when the current load transitions from a provisional to a 
1152     // committed state, pending redirects may be cancelled. 
1153     if (duringLoad)
1154         stopLoading(true);   
1155
1156     ScheduledRedirection::Type type = duringLoad
1157         ? ScheduledRedirection::locationChangeDuringLoad : ScheduledRedirection::locationChange;
1158     scheduleRedirection(new ScheduledRedirection(type, m_URL.url(), m_outgoingReferrer, true, wasUserGesture));
1159     m_cachePolicy = CachePolicyRefresh;
1160 }
1161
1162 bool FrameLoader::isScheduledLocationChangePending() const
1163 {
1164     if (!m_scheduledRedirection)
1165         return false;
1166     switch (m_scheduledRedirection->type) {
1167         case ScheduledRedirection::redirection:
1168             return false;
1169         case ScheduledRedirection::historyNavigation:
1170         case ScheduledRedirection::locationChange:
1171         case ScheduledRedirection::locationChangeDuringLoad:
1172             return true;
1173     }
1174     ASSERT_NOT_REACHED();
1175     return false;
1176 }
1177
1178 void FrameLoader::scheduleHistoryNavigation(int steps)
1179 {
1180     // navigation will always be allowed in the 0 steps case, which is OK because
1181     // that's supposed to force a reload.
1182     if (!canGoBackOrForward(steps)) {
1183         cancelRedirection();
1184         return;
1185     }
1186
1187     // If the URL we're going to navigate to is the same as the current one, except for the
1188     // fragment part, we don't need to schedule the navigation.
1189     if (equalIgnoringRef(m_URL, historyURL(steps))) {
1190         goBackOrForward(steps);
1191         return;
1192     }
1193     
1194     scheduleRedirection(new ScheduledRedirection(steps));
1195 }
1196
1197 void FrameLoader::redirectionTimerFired(Timer<FrameLoader>*)
1198 {
1199     OwnPtr<ScheduledRedirection> redirection(m_scheduledRedirection.release());
1200
1201     switch (redirection->type) {
1202         case ScheduledRedirection::redirection:
1203         case ScheduledRedirection::locationChange:
1204         case ScheduledRedirection::locationChangeDuringLoad:
1205             changeLocation(redirection->URL, redirection->referrer,
1206                 redirection->lockHistory, redirection->wasUserGesture);
1207             return;
1208         case ScheduledRedirection::historyNavigation:
1209             if (redirection->historySteps == 0) {
1210                 // Special case for go(0) from a frame -> reload only the frame
1211                 urlSelected(m_URL, "", 0);
1212                 return;
1213             }
1214             // go(i!=0) from a frame navigates into the history of the frame only,
1215             // in both IE and NS (but not in Mozilla). We can't easily do that.
1216             goBackOrForward(redirection->historySteps);
1217             return;
1218     }
1219     ASSERT_NOT_REACHED();
1220 }
1221
1222 String FrameLoader::encoding() const
1223 {
1224     if (m_encodingWasChosenByUser && !m_encoding.isEmpty())
1225         return m_encoding;
1226     if (m_decoder && m_decoder->encoding().isValid())
1227         return m_decoder->encoding().name();
1228     return m_frame->settings()->encoding();
1229 }
1230
1231 bool FrameLoader::gotoAnchor(const String& name)
1232 {
1233     if (!m_frame->document())
1234         return false;
1235
1236     Node* anchorNode = m_frame->document()->getElementById(AtomicString(name));
1237     if (!anchorNode)
1238         anchorNode = m_frame->document()->anchors()->namedItem(name, !m_frame->document()->inCompatMode());
1239
1240     m_frame->document()->setCSSTarget(anchorNode); // Setting to null will clear the current target.
1241   
1242     // Implement the rule that "" and "top" both mean top of page as in other browsers.
1243     if (!anchorNode && !(name.isEmpty() || equalIgnoringCase(name, "top")))
1244         return false;
1245
1246     // We need to update the layout before scrolling, otherwise we could
1247     // really mess things up if an anchor scroll comes at a bad moment.
1248     if (m_frame->document()) {
1249         m_frame->document()->updateRendering();
1250         // Only do a layout if changes have occurred that make it necessary.      
1251         if (m_frame->view() && m_frame->document()->renderer() && m_frame->document()->renderer()->needsLayout())
1252             m_frame->view()->layout();
1253     }
1254   
1255     // Scroll nested layers and frames to reveal the anchor.
1256     // Align to the top and to the closest side (this matches other browsers).
1257     RenderObject* renderer;
1258     IntRect rect;
1259     if (!anchorNode)
1260         renderer = m_frame->document()->renderer(); // top of document
1261     else {
1262         renderer = anchorNode->renderer();
1263         rect = anchorNode->getRect();
1264     }
1265     if (renderer)
1266         renderer->enclosingLayer()->scrollRectToVisible(rect, RenderLayer::gAlignToEdgeIfNeeded, RenderLayer::gAlignTopAlways);
1267
1268     return true;
1269 }
1270
1271 bool FrameLoader::requestObject(RenderPart* renderer, const String& url, const AtomicString& frameName,
1272     const String& mimeType, const Vector<String>& paramNames, const Vector<String>& paramValues)
1273 {
1274     if (url.isEmpty() && mimeType.isEmpty())
1275         return true;
1276
1277     KURL completedURL;
1278     if (!url.isEmpty())
1279         completedURL = completeURL(url);
1280
1281     bool useFallback;
1282     if (shouldUsePlugin(renderer->element(), completedURL, mimeType, renderer->hasFallbackContent(), useFallback))
1283         return loadPlugin(renderer, completedURL, mimeType, paramNames, paramValues, useFallback);
1284
1285     ASSERT(renderer->node()->hasTagName(objectTag) || renderer->node()->hasTagName(embedTag));
1286     AtomicString uniqueFrameName = m_frame->tree()->uniqueChildName(frameName);
1287     static_cast<HTMLPlugInElement*>(renderer->node())->setFrameName(uniqueFrameName);
1288     
1289     // FIXME: OK to always make a new one? When does the old frame get removed?
1290     return loadSubframe(static_cast<Element*>(renderer->node()), completedURL, uniqueFrameName, m_outgoingReferrer);
1291 }
1292
1293 bool FrameLoader::shouldUsePlugin(Node* element, const KURL& url, const String& mimeType, bool hasFallback, bool& useFallback)
1294 {
1295     ObjectContentType objectType = objectContentType(url, mimeType);
1296     // If an object's content can't be handled and it has no fallback, let
1297     // it be handled as a plugin to show the broken plugin icon.
1298     useFallback = objectType == ObjectContentNone && hasFallback;
1299     return objectType == ObjectContentNone || objectType == ObjectContentPlugin;
1300 }
1301
1302 bool FrameLoader::loadPlugin(RenderPart* renderer, const KURL& url, const String& mimeType, 
1303     const Vector<String>& paramNames, const Vector<String>& paramValues, bool useFallback)
1304 {
1305     Widget* widget = 0;
1306
1307     if (renderer && !useFallback) {
1308         Element* pluginElement = 0;
1309         if (renderer->node() && renderer->node()->isElementNode())
1310             pluginElement = static_cast<Element*>(renderer->node());
1311
1312         widget = createPlugin(pluginElement, url, paramNames, paramValues, mimeType);
1313         if (widget) {
1314             renderer->setWidget(widget);
1315             m_containsPlugIns = true;
1316         }
1317     }
1318
1319     checkEmitLoadEvent();
1320     return widget != 0;
1321 }
1322
1323 void FrameLoader::clearRecordedFormValues()
1324 {
1325     m_formAboutToBeSubmitted = 0;
1326     m_formValuesAboutToBeSubmitted.clear();
1327 }
1328
1329 void FrameLoader::recordFormValue(const String& name, const String& value, PassRefPtr<HTMLFormElement> element)
1330 {
1331     m_formAboutToBeSubmitted = element;
1332     m_formValuesAboutToBeSubmitted.set(name, value);
1333 }
1334
1335 void FrameLoader::parentCompleted()
1336 {
1337     if (m_scheduledRedirection && !m_redirectionTimer.isActive())
1338         startRedirectionTimer();
1339 }
1340
1341 String FrameLoader::outgoingReferrer() const
1342 {
1343     return m_outgoingReferrer;
1344 }
1345
1346 String FrameLoader::lastModified() const
1347 {
1348     return m_responseModifiedHeader;
1349 }
1350
1351 Frame* FrameLoader::opener()
1352 {
1353     return m_opener;
1354 }
1355
1356 void FrameLoader::setOpener(Frame* opener)
1357 {
1358     if (m_opener)
1359         m_opener->loader()->m_openedFrames.remove(m_frame);
1360     if (opener)
1361         opener->loader()->m_openedFrames.add(m_frame);
1362     m_opener = opener;
1363 }
1364
1365 bool FrameLoader::openedByJavaScript()
1366 {
1367     return m_openedByJavaScript;
1368 }
1369
1370 void FrameLoader::setOpenedByJavaScript()
1371 {
1372     m_openedByJavaScript = true;
1373 }
1374
1375 void FrameLoader::handleFallbackContent()
1376 {
1377     Element* owner = m_frame->ownerElement();
1378     if (!owner || !owner->hasTagName(objectTag))
1379         return;
1380     static_cast<HTMLObjectElement*>(owner)->renderFallbackContent();
1381 }
1382
1383 void FrameLoader::provisionalLoadStarted()
1384 {
1385     m_firstLayoutDone = false;
1386     cancelRedirection(true);
1387     m_client->provisionalLoadStarted();
1388 }
1389
1390 bool FrameLoader::userGestureHint()
1391 {
1392     Frame* rootFrame = m_frame;
1393     while (rootFrame->tree()->parent())
1394         rootFrame = rootFrame->tree()->parent();
1395
1396     if (rootFrame->scriptProxy())
1397         return rootFrame->scriptProxy()->interpreter()->wasRunByUserGesture();
1398
1399     return true; // If JavaScript is disabled, a user gesture must have initiated the navigation
1400 }
1401
1402 void FrameLoader::didNotOpenURL(const KURL& URL)
1403 {
1404     if (m_submittedFormURL == URL)
1405         m_submittedFormURL = KURL();
1406 }
1407
1408 void FrameLoader::resetMultipleFormSubmissionProtection()
1409 {
1410     m_submittedFormURL = KURL();
1411 }
1412
1413 void FrameLoader::setEncoding(const String& name, bool userChosen)
1414 {
1415     if (!m_workingURL.isEmpty())
1416         receivedFirstData();
1417     m_encoding = name;
1418     m_encodingWasChosenByUser = userChosen;
1419 }
1420
1421 void FrameLoader::addData(const char* bytes, int length)
1422 {
1423     ASSERT(m_workingURL.isEmpty());
1424     ASSERT(m_frame->document());
1425     ASSERT(m_frame->document()->parsing());
1426     write(bytes, length);
1427 }
1428
1429 bool FrameLoader::canCachePage()
1430 {
1431     return m_frame->document()
1432         && !m_frame->tree()->childCount()
1433         && !m_frame->tree()->parent()
1434         && !m_containsPlugIns
1435         && !m_URL.protocol().startsWith("https")
1436         && !m_frame->document()->applets()->length()
1437         && !m_frame->document()->hasWindowEventListener(unloadEvent)
1438         && !m_frame->document()->hasPasswordField();
1439 }
1440
1441 void FrameLoader::updatePolicyBaseURL()
1442 {
1443     if (m_frame->tree()->parent() && m_frame->tree()->parent()->document())
1444         setPolicyBaseURL(m_frame->tree()->parent()->document()->policyBaseURL());
1445     else
1446         setPolicyBaseURL(m_URL.url());
1447 }
1448
1449 void FrameLoader::setPolicyBaseURL(const String& s)
1450 {
1451     if (m_frame->document())
1452         m_frame->document()->setPolicyBaseURL(s);
1453     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
1454         child->loader()->setPolicyBaseURL(s);
1455 }
1456
1457 // This does the same kind of work that FrameLoader::openURL does, except it relies on the fact
1458 // that a higher level already checked that the URLs match and the scrolling is the right thing to do.
1459 void FrameLoader::scrollToAnchor(const KURL& URL)
1460 {
1461     m_URL = URL;
1462     started();
1463
1464     gotoAnchor();
1465
1466     // It's important to model this as a load that starts and immediately finishes.
1467     // Otherwise, the parent frame may think we never finished loading.
1468     m_isComplete = false;
1469     checkCompleted();
1470 }
1471
1472 bool FrameLoader::isComplete() const
1473 {
1474     return m_isComplete;
1475 }
1476
1477 bool FrameLoader::isLoadingMainResource() const
1478 {
1479     return m_isLoadingMainResource;
1480 }
1481
1482 KURL FrameLoader::url() const
1483 {
1484     return m_URL;
1485 }
1486
1487 void FrameLoader::scheduleRedirection(ScheduledRedirection* redirection)
1488 {
1489     stopRedirectionTimer();
1490     m_scheduledRedirection.set(redirection);
1491     if (m_isComplete)
1492         startRedirectionTimer();
1493 }
1494
1495 void FrameLoader::startRedirectionTimer()
1496 {
1497     ASSERT(m_scheduledRedirection);
1498
1499     m_redirectionTimer.stop();
1500     m_redirectionTimer.startOneShot(m_scheduledRedirection->delay);
1501
1502     switch (m_scheduledRedirection->type) {
1503         case ScheduledRedirection::redirection:
1504         case ScheduledRedirection::locationChange:
1505         case ScheduledRedirection::locationChangeDuringLoad:
1506             clientRedirected(m_scheduledRedirection->URL.deprecatedString(),
1507                 m_scheduledRedirection->delay,
1508                 currentTime() + m_redirectionTimer.nextFireInterval(),
1509                 m_scheduledRedirection->lockHistory,
1510                 m_isExecutingJavaScriptFormAction);
1511             return;
1512         case ScheduledRedirection::historyNavigation:
1513             // Don't report history navigations.
1514             return;
1515     }
1516     ASSERT_NOT_REACHED();
1517 }
1518
1519 void FrameLoader::stopRedirectionTimer()
1520 {
1521     if (!m_redirectionTimer.isActive())
1522         return;
1523
1524     m_redirectionTimer.stop();
1525
1526     if (m_scheduledRedirection) {
1527         switch (m_scheduledRedirection->type) {
1528             case ScheduledRedirection::redirection:
1529             case ScheduledRedirection::locationChange:
1530             case ScheduledRedirection::locationChangeDuringLoad:
1531                 clientRedirectCancelledOrFinished(m_cancellingWithLoadInProgress);
1532                 return;
1533             case ScheduledRedirection::historyNavigation:
1534                 // Don't report history navigations.
1535                 return;
1536         }
1537         ASSERT_NOT_REACHED();
1538     }
1539 }
1540
1541 void FrameLoader::updateBaseURLForEmptyDocument()
1542 {
1543     Element* owner = m_frame->ownerElement();
1544     // FIXME: Should embed be included?
1545     if (owner && (owner->hasTagName(iframeTag) || owner->hasTagName(objectTag) || owner->hasTagName(embedTag)))
1546         m_frame->document()->setBaseURL(m_frame->tree()->parent()->document()->baseURL());
1547 }
1548
1549 void FrameLoader::completed()
1550 {
1551     RefPtr<Frame> protect(m_frame);
1552     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
1553         child->loader()->parentCompleted();
1554     if (Frame* parent = m_frame->tree()->parent())
1555         parent->loader()->checkCompleted();
1556     submitFormAgain();
1557 }
1558
1559 void FrameLoader::started()
1560 {
1561     for (Frame* frame = m_frame; frame; frame = frame->tree()->parent())
1562         frame->loader()->m_isComplete = false;
1563 }
1564
1565 bool FrameLoader::containsPlugins() const 
1566
1567     return m_containsPlugIns;
1568 }
1569
1570 void FrameLoader::prepareForLoadStart()
1571 {
1572     m_client->progressStarted();
1573     m_client->dispatchDidStartProvisionalLoad();
1574 }
1575
1576 void FrameLoader::setupForReplace()
1577 {
1578     setState(FrameStateProvisional);
1579     m_provisionalDocumentLoader = m_documentLoader;
1580     m_documentLoader = 0;
1581     detachChildren();
1582 }
1583
1584 void FrameLoader::setupForReplaceByMIMEType(const String& newMIMEType)
1585 {
1586     activeDocumentLoader()->setupForReplaceByMIMEType(newMIMEType);
1587 }
1588
1589 void FrameLoader::finalSetupForReplace(DocumentLoader* loader)
1590 {
1591     m_client->clearUnarchivingState(loader);
1592 }
1593
1594 #if PLATFORM(MAC)
1595 void FrameLoader::load(const KURL& URL, Event* event)
1596 {
1597     load(ResourceRequest(URL), true, event, 0, HashMap<String, String>());
1598 }
1599 #endif
1600
1601 bool FrameLoader::canTarget(Frame* target) const
1602 {
1603     // This method prevents this exploit:
1604     // <rdar://problem/3715785> multiple frame injection vulnerability reported by Secunia, affects almost all browsers
1605
1606     if (!target)
1607         return true;
1608
1609     // Allow with navigation within the same page/frameset.
1610     if (m_frame->page() == target->page())
1611         return true;
1612
1613     String domain;
1614     if (Document* document = m_frame->document())
1615         domain = document->domain();
1616     // Allow if the request is made from a local file.
1617     if (domain.isEmpty())
1618         return true;
1619     
1620     Frame* parent = target->tree()->parent();
1621     // Allow if target is an entire window.
1622     if (!parent)
1623         return true;
1624     
1625     String parentDomain;
1626     if (Document* parentDocument = parent->document())
1627         domain = parentDocument->domain();
1628     // Allow if the domain of the parent of the targeted frame equals this domain.
1629     return equalIgnoringCase(parentDomain, domain);
1630 }
1631
1632 void FrameLoader::stopLoadingPlugIns()
1633 {
1634     cancelAll(m_plugInStreamLoaders);
1635 }
1636
1637 void FrameLoader::stopLoadingSubresources()
1638 {
1639     cancelAll(m_subresourceLoaders);
1640 }
1641
1642 void FrameLoader::stopLoadingSubframes()
1643 {
1644     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
1645         child->loader()->stopAllLoaders();
1646 }
1647
1648 void FrameLoader::stopAllLoaders()
1649 {
1650     // If this method is called from within this method, infinite recursion can occur (3442218). Avoid this.
1651     if (m_inStopAllLoaders)
1652         return;
1653
1654     m_inStopAllLoaders = true;
1655
1656     stopPolicyCheck();
1657
1658     stopLoadingSubframes();
1659     if (m_provisionalDocumentLoader)
1660         m_provisionalDocumentLoader->stopLoading();
1661     if (m_documentLoader)
1662         m_documentLoader->stopLoading();
1663     setProvisionalDocumentLoader(0);
1664     m_client->clearArchivedResources();
1665
1666     m_inStopAllLoaders = false;    
1667 }
1668
1669 void FrameLoader::cancelMainResourceLoad()
1670 {
1671     if (m_mainResourceLoader)
1672         m_mainResourceLoader->cancel();
1673 }
1674
1675 void FrameLoader::cancelPendingArchiveLoad(ResourceLoader* loader)
1676 {
1677     m_client->cancelPendingArchiveLoad(loader);
1678 }
1679
1680 DocumentLoader* FrameLoader::activeDocumentLoader() const
1681 {
1682     if (m_state == FrameStateProvisional)
1683         return m_provisionalDocumentLoader.get();
1684     return m_documentLoader.get();
1685 }
1686
1687 void FrameLoader::addPlugInStreamLoader(ResourceLoader* loader)
1688 {
1689     m_plugInStreamLoaders.add(loader);
1690     activeDocumentLoader()->setLoading(true);
1691 }
1692
1693 void FrameLoader::removePlugInStreamLoader(ResourceLoader* loader)
1694 {
1695     m_plugInStreamLoaders.remove(loader);
1696     activeDocumentLoader()->updateLoading();
1697 }
1698
1699 bool FrameLoader::hasMainResourceLoader() const
1700 {
1701     return m_mainResourceLoader != 0;
1702 }
1703
1704 bool FrameLoader::isLoadingSubresources() const
1705 {
1706     return !m_subresourceLoaders.isEmpty();
1707 }
1708
1709 bool FrameLoader::isLoadingPlugIns() const
1710 {
1711     return !m_plugInStreamLoaders.isEmpty();
1712 }
1713
1714 bool FrameLoader::isLoading() const
1715 {
1716     return isLoadingMainResource() || isLoadingSubresources() || isLoadingPlugIns();
1717 }
1718
1719 void FrameLoader::addSubresourceLoader(ResourceLoader* loader)
1720 {
1721     ASSERT(!m_provisionalDocumentLoader);
1722     m_subresourceLoaders.add(loader);
1723     activeDocumentLoader()->setLoading(true);
1724 }
1725
1726 void FrameLoader::removeSubresourceLoader(ResourceLoader* loader)
1727 {
1728     m_subresourceLoaders.remove(loader);
1729     activeDocumentLoader()->updateLoading();
1730     checkLoadComplete();
1731 }
1732
1733 void FrameLoader::releaseMainResourceLoader()
1734 {
1735     m_mainResourceLoader = 0;
1736 }
1737
1738 void FrameLoader::setDocumentLoader(DocumentLoader* loader)
1739 {
1740     if (!loader && !m_documentLoader)
1741         return;
1742     
1743     ASSERT(loader != m_documentLoader);
1744     ASSERT(!loader || loader->frameLoader() == this);
1745
1746     m_client->prepareForDataSourceReplacement();
1747     if (m_documentLoader)
1748         m_documentLoader->detachFromFrame();
1749
1750     m_documentLoader = loader;
1751 }
1752
1753 DocumentLoader* FrameLoader::documentLoader() const
1754 {
1755     return m_documentLoader.get();
1756 }
1757
1758 void FrameLoader::setPolicyDocumentLoader(DocumentLoader* loader)
1759 {
1760     if (m_policyDocumentLoader == loader)
1761         return;
1762
1763     ASSERT(m_frame);
1764     if (loader)
1765         loader->setFrame(m_frame);
1766     if (m_policyDocumentLoader
1767             && m_policyDocumentLoader != m_provisionalDocumentLoader
1768             && m_policyDocumentLoader != m_documentLoader)
1769         m_policyDocumentLoader->detachFromFrame();
1770
1771     m_policyDocumentLoader = loader;
1772 }
1773    
1774 DocumentLoader* FrameLoader::provisionalDocumentLoader()
1775 {
1776     return m_provisionalDocumentLoader.get();
1777 }
1778
1779 void FrameLoader::setProvisionalDocumentLoader(DocumentLoader* loader)
1780 {
1781     ASSERT(!loader || !m_provisionalDocumentLoader);
1782     ASSERT(!loader || loader->frameLoader() == this);
1783
1784     if (m_provisionalDocumentLoader && m_provisionalDocumentLoader != m_documentLoader)
1785         m_provisionalDocumentLoader->detachFromFrame();
1786
1787     m_provisionalDocumentLoader = loader;
1788 }
1789
1790 FrameState FrameLoader::state() const
1791 {
1792     return m_state;
1793 }
1794
1795 double FrameLoader::timeOfLastCompletedLoad()
1796 {
1797     return storedTimeOfLastCompletedLoad;
1798 }
1799
1800 void FrameLoader::setState(FrameState newState)
1801 {    
1802     m_state = newState;
1803     
1804     if (newState == FrameStateProvisional)
1805         provisionalLoadStarted();
1806     else if (newState == FrameStateComplete) {
1807         frameLoadCompleted();
1808         storedTimeOfLastCompletedLoad = currentTime();
1809         if (m_documentLoader)
1810             m_documentLoader->stopRecordingResponses();
1811     }
1812 }
1813
1814 void FrameLoader::clearProvisionalLoad()
1815 {
1816     setProvisionalDocumentLoader(0);
1817     m_client->progressCompleted();
1818     setState(FrameStateComplete);
1819 }
1820
1821 void FrameLoader::markLoadComplete()
1822 {
1823     setState(FrameStateComplete);
1824 }
1825
1826 void FrameLoader::commitProvisionalLoad()
1827 {
1828     stopLoadingSubresources();
1829     stopLoadingPlugIns();
1830
1831     setDocumentLoader(m_provisionalDocumentLoader.get());
1832     setProvisionalDocumentLoader(0);
1833     setState(FrameStateCommittedPage);
1834 }
1835
1836 bool FrameLoader::privateBrowsingEnabled() const
1837 {
1838     return m_client->privateBrowsingEnabled();
1839 }
1840
1841 void FrameLoader::clientRedirectCancelledOrFinished(bool cancelWithLoadInProgress)
1842 {
1843     // Note that -webView:didCancelClientRedirectForFrame: is called on the frame load delegate even if
1844     // the redirect succeeded.  We should either rename this API, or add a new method, like
1845     // -webView:didFinishClientRedirectForFrame:
1846     m_client->dispatchDidCancelClientRedirect();
1847
1848     if (!cancelWithLoadInProgress)
1849         m_quickRedirectComing = false;
1850
1851     m_sentRedirectNotification = false;
1852 }
1853
1854 void FrameLoader::clientRedirected(const KURL& URL, double seconds, double fireDate, bool lockHistory, bool isJavaScriptFormAction)
1855 {
1856     m_client->dispatchWillPerformClientRedirect(URL, seconds, fireDate);
1857     
1858     // Remember that we sent a redirect notification to the frame load delegate so that when we commit
1859     // the next provisional load, we can send a corresponding -webView:didCancelClientRedirectForFrame:
1860     m_sentRedirectNotification = true;
1861     
1862     // If a "quick" redirect comes in an, we set a special mode so we treat the next
1863     // load as part of the same navigation. If we don't have a document loader, we have
1864     // no "original" load on which to base a redirect, so we treat the redirect as a normal load.
1865     m_quickRedirectComing = lockHistory && m_documentLoader && !isJavaScriptFormAction;
1866 }
1867
1868 bool FrameLoader::shouldReload(const KURL& currentURL, const KURL& destinationURL)
1869 {
1870     // This function implements the rule: "Don't reload if navigating by fragment within
1871     // the same URL, but do reload if going to a new URL or to the same URL with no
1872     // fragment identifier at all."
1873     if (!currentURL.hasRef() && !destinationURL.hasRef())
1874         return true;
1875     return !equalIgnoringRef(currentURL, destinationURL);
1876 }
1877
1878 void FrameLoader::closeOldDataSources()
1879 {
1880     // FIXME: Is it important for this traversal to be postorder instead of preorder?
1881     // If so, add helpers for postorder traversal, and use them. If not, then lets not
1882     // use a recursive algorithm here.
1883     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
1884         child->loader()->closeOldDataSources();
1885     
1886     if (m_documentLoader)
1887         m_client->dispatchWillClose();
1888
1889     m_client->setMainFrameDocumentReady(false); // stop giving out the actual DOMDocument to observers
1890 }
1891
1892 void FrameLoader::open(PageState& state)
1893 {
1894     ASSERT(m_frame->page()->mainFrame() == m_frame);
1895
1896     cancelRedirection();
1897
1898     // We still have to close the previous part page.
1899     closeURL();
1900
1901     m_isComplete = false;
1902     
1903     // Don't re-emit the load event.
1904     m_wasLoadEventEmitted = true;
1905     
1906     // Delete old status bar messages (if it _was_ activated on last URL).
1907     if (m_frame->javaScriptEnabled()) {
1908         m_frame->d->m_kjsStatusBarText = String();
1909         m_frame->d->m_kjsDefaultStatusBarText = String();
1910     }
1911
1912     KURL URL = state.URL();
1913
1914     if (URL.protocol().startsWith("http") && !URL.host().isEmpty() && URL.path().isEmpty())
1915         URL.setPath("/");
1916     
1917     m_URL = URL;
1918     m_workingURL = URL;
1919
1920     started();
1921
1922     clear();
1923
1924     Document* document = state.document();
1925     document->setInPageCache(false);
1926
1927     m_needsClear = true;
1928     m_isComplete = false;
1929     m_wasLoadEventEmitted = false;
1930     m_outgoingReferrer = URL.url();
1931     
1932     m_frame->setView(document->view());
1933     
1934     m_frame->d->m_doc = document;
1935     m_frame->d->m_mousePressNode = state.mousePressNode();
1936     m_decoder = document->decoder();
1937
1938     updatePolicyBaseURL();
1939
1940     state.restoreJavaScriptState(m_frame->page());
1941
1942     checkCompleted();
1943 }
1944
1945 bool FrameLoader::isStopping() const
1946 {
1947     return activeDocumentLoader()->isStopping();
1948 }
1949
1950 void FrameLoader::finishedLoading()
1951 {
1952     // Retain because the stop may release the last reference to it.
1953     RefPtr<Frame> protect(m_frame);
1954
1955 #if PLATFORM(MAC)
1956     RefPtr<DocumentLoader> dl = activeDocumentLoader();
1957     dl->finishedLoading();
1958     if (dl->mainDocumentError() || !dl->frameLoader())
1959         return;
1960     dl->setPrimaryLoadComplete(true);
1961     m_client->dispatchDidLoadMainResource(dl.get());
1962 #endif
1963     checkLoadComplete();
1964 }
1965
1966 KURL FrameLoader::URL() const
1967 {
1968     return activeDocumentLoader()->URL();
1969 }
1970
1971 bool FrameLoader::isArchiveLoadPending(ResourceLoader* loader) const
1972 {
1973     return m_client->isArchiveLoadPending(loader);
1974 }
1975
1976 bool FrameLoader::isHostedByObjectElement() const
1977 {
1978     Element* owner = m_frame->ownerElement();
1979     return owner && owner->hasTagName(objectTag);
1980 }
1981
1982 bool FrameLoader::isLoadingMainFrame() const
1983 {
1984     Page* page = m_frame->page();
1985     return page && m_frame == page->mainFrame();
1986 }
1987
1988 bool FrameLoader::canShowMIMEType(const String& MIMEType) const
1989 {
1990     return m_client->canShowMIMEType(MIMEType);
1991 }
1992
1993 bool FrameLoader::representationExistsForURLScheme(const String& URLScheme)
1994 {
1995     return m_client->representationExistsForURLScheme(URLScheme);
1996 }
1997
1998 String FrameLoader::generatedMIMETypeForURLScheme(const String& URLScheme)
1999 {
2000     return m_client->generatedMIMETypeForURLScheme(URLScheme);
2001 }
2002
2003 void FrameLoader::cancelContentPolicyCheck()
2004 {
2005     m_client->cancelPolicyCheck();
2006     m_policyCheck.clear();
2007 }
2008
2009 void FrameLoader::didReceiveServerRedirectForProvisionalLoadForFrame()
2010 {
2011     m_client->dispatchDidReceiveServerRedirectForProvisionalLoad();
2012 }
2013
2014 void FrameLoader::finishedLoadingDocument(DocumentLoader* loader)
2015 {
2016     m_client->finishedLoading(loader);
2017 }
2018
2019 bool FrameLoader::isReplacing() const
2020 {
2021     return m_loadType == FrameLoadTypeReplace;
2022 }
2023
2024 void FrameLoader::setReplacing()
2025 {
2026     m_loadType = FrameLoadTypeReplace;
2027 }
2028
2029 void FrameLoader::revertToProvisional(DocumentLoader* loader)
2030 {
2031     m_client->revertToProvisionalState(loader);
2032 }
2033
2034 bool FrameLoader::subframeIsLoading() const
2035 {
2036     // It's most likely that the last added frame is the last to load so we walk backwards.
2037     for (Frame* child = m_frame->tree()->lastChild(); child; child = child->tree()->previousSibling()) {
2038         FrameLoader* childLoader = child->loader();
2039         DocumentLoader* documentLoader = childLoader->documentLoader();
2040         if (documentLoader && documentLoader->isLoadingInAPISense())
2041             return true;
2042         documentLoader = childLoader->provisionalDocumentLoader();
2043         if (documentLoader && documentLoader->isLoadingInAPISense())
2044             return true;
2045     }
2046     return false;
2047 }
2048
2049 void FrameLoader::willChangeTitle(DocumentLoader* loader)
2050 {
2051     m_client->willChangeTitle(loader);
2052 }
2053
2054 FrameLoadType FrameLoader::loadType() const
2055 {
2056     return m_loadType;
2057 }
2058
2059 void FrameLoader::stopPolicyCheck()
2060 {
2061     m_client->cancelPolicyCheck();
2062     PolicyCheck check = m_policyCheck;
2063     m_policyCheck.clear();
2064     check.clearRequest();
2065     check.call();
2066 }
2067
2068 void FrameLoader::continueAfterContentPolicy(PolicyAction policy)
2069 {
2070     PolicyCheck check = m_policyCheck;
2071     m_policyCheck.clear();
2072     check.call(policy);
2073 }
2074
2075 #if PLATFORM(MAC)
2076 void FrameLoader::continueAfterWillSubmitForm(PolicyAction)
2077 {
2078     startLoading();
2079 }
2080 #endif
2081
2082 #if PLATFORM(MAC)
2083 void FrameLoader::didFirstLayout()
2084 {
2085     if (isBackForwardLoadType(m_loadType) && m_client->hasBackForwardList())
2086         m_client->restoreScrollPositionAndViewState();
2087
2088     m_firstLayoutDone = true;
2089     m_client->dispatchDidFirstLayout();
2090 }
2091 #endif
2092
2093 void FrameLoader::frameLoadCompleted()
2094 {
2095     m_client->frameLoadCompleted();
2096
2097     // After a canceled provisional load, firstLayoutDone is false.
2098     // Reset it to true if we're displaying a page.
2099     if (m_documentLoader)
2100         m_firstLayoutDone = true;
2101 }
2102
2103 bool FrameLoader::firstLayoutDone() const
2104 {
2105     return m_firstLayoutDone;
2106 }
2107
2108 bool FrameLoader::isQuickRedirectComing() const
2109 {
2110     return m_quickRedirectComing;
2111 }
2112
2113 void FrameLoader::closeDocument()
2114 {
2115     m_client->willCloseDocument();
2116     closeURL();
2117 }
2118
2119 void FrameLoader::detachChildren()
2120 {
2121     // FIXME: Is it really necessary to do this in reverse order?
2122     Frame* previous;
2123     for (Frame* child = m_frame->tree()->lastChild(); child; child = previous) {
2124         previous = child->tree()->previousSibling();
2125         child->loader()->detachFromParent();
2126     }
2127 }
2128
2129 // Called every time a resource is completely loaded, or an error is received.
2130 void FrameLoader::checkLoadComplete()
2131 {
2132     ASSERT(m_client->hasWebView());
2133     for (RefPtr<Frame> frame = m_frame; frame; frame = frame->tree()->parent())
2134         frame->loader()->checkLoadCompleteForThisFrame();
2135 }
2136
2137 int FrameLoader::numPendingOrLoadingRequests(bool recurse) const
2138 {
2139     if (!recurse)
2140         return numRequests(m_frame->document());
2141
2142     int count = 0;
2143     for (Frame* frame = m_frame; frame; frame = frame->tree()->traverseNext(m_frame))
2144         count += numRequests(frame->document());
2145     return count;
2146 }
2147
2148 void FrameLoader::setClient(PassRefPtr<FrameLoaderClient> client)
2149 {
2150     ASSERT(client);
2151     ASSERT(!m_client);
2152     m_client = client;
2153 }
2154
2155 FrameLoaderClient* FrameLoader::client() const
2156 {
2157     return m_client.get();
2158 }
2159
2160 #if PLATFORM(MAC)
2161 void FrameLoader::submitForm(const FrameLoadRequest& request, Event* event)
2162 {
2163     // FIXME: We'd like to remove this altogether and fix the multiple form submission issue another way.
2164     // We do not want to submit more than one form from the same page,
2165     // nor do we want to submit a single form more than once.
2166     // This flag prevents these from happening; not sure how other browsers prevent this.
2167     // The flag is reset in each time we start handle a new mouse or key down event, and
2168     // also in setView since this part may get reused for a page from the back/forward cache.
2169     // The form multi-submit logic here is only needed when we are submitting a form that affects this frame.
2170     // FIXME: Frame targeting is only one of the ways the submission could end up doing something other
2171     // than replacing this frame's content, so this check is flawed. On the other hand, the check is hardly
2172     // needed any more now that we reset m_submittedFormURL on each mouse or key down event.
2173     Frame* target = m_frame->tree()->find(request.frameName());
2174     if (m_frame->tree()->isDescendantOf(target)) {
2175         if (m_submittedFormURL == request.resourceRequest().url())
2176             return;
2177         m_submittedFormURL = request.resourceRequest().url();
2178     }
2179
2180     // FIXME: Why do we always pass true for userGesture?
2181     load(request, true, event, m_formAboutToBeSubmitted.get(), m_formValuesAboutToBeSubmitted);
2182
2183     clearRecordedFormValues();
2184 }
2185 #endif
2186
2187 #if PLATFORM(MAC)
2188 void FrameLoader::urlSelected(const FrameLoadRequest& request, Event* event)
2189 {
2190     FrameLoadRequest copy = request;
2191     if (copy.resourceRequest().httpReferrer().isEmpty())
2192         copy.resourceRequest().setHTTPReferrer(m_outgoingReferrer);
2193
2194     // FIXME: Why do we always pass true for userGesture?
2195     load(copy, true, event, 0, HashMap<String, String>());
2196 }
2197 #endif
2198
2199 String FrameLoader::userAgent() const
2200 {
2201     return m_client->userAgent();
2202 }
2203
2204 void FrameLoader::createEmptyDocument()
2205 {
2206     // Although it's not completely clear from the name of this function,
2207     // it does nothing if we already have a document, and just creates an
2208     // empty one if we have no document at all.
2209 #if PLATFORM(MAC)
2210     if (!m_frame->document()) {
2211         loadEmptyDocumentSynchronously();
2212         updateBaseURLForEmptyDocument();
2213     }
2214 #elif PLATFORM(QT)
2215     if (!m_frame->document()) {
2216         begin();
2217         end();
2218     }
2219 #endif
2220 }
2221
2222 void FrameLoader::tokenizerProcessedData()
2223 {
2224     if (m_frame->document())
2225         checkCompleted();
2226     checkLoadComplete();
2227 }
2228
2229 void FrameLoader::didTellBridgeAboutLoad(const String& URL)
2230 {
2231     m_urlsBridgeKnowsAbout.add(URL);
2232 }
2233
2234 bool FrameLoader::haveToldBridgeAboutLoad(const String& URL)
2235 {
2236     return m_urlsBridgeKnowsAbout.contains(URL);
2237 }
2238
2239 void FrameLoader::handledOnloadEvents()
2240 {
2241     m_client->dispatchDidHandleOnloadEvents();
2242 }
2243
2244 void FrameLoader::frameDetached()
2245 {
2246     stopAllLoaders();
2247     detachFromParent();
2248 }
2249
2250 #if PLATFORM(MAC)
2251 void FrameLoader::setTitle(const String& title)
2252 {
2253     documentLoader()->setTitle(title);
2254 }
2255 #endif
2256
2257 } // namespace WebCore