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