b53bc6c2bb3bf9dad7c8cdaadd9dd44d0b51cd2f
[WebKit-https.git] / WebCore / page / Frame.cpp
1 /* This file is part of the KDE project
2  *
3  * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
4  *                     1999 Lars Knoll <knoll@kde.org>
5  *                     1999 Antti Koivisto <koivisto@kde.org>
6  *                     2000 Simon Hausmann <hausmann@kde.org>
7  *                     2000 Stefan Schimanski <1Stein@gmx.de>
8  *                     2001 George Staikos <staikos@kde.org>
9  * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
10  * Copyright (C) 2005 Alexey Proskuryakov <ap@nypop.com>
11  *
12  * This library is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Library General Public
14  * License as published by the Free Software Foundation; either
15  * version 2 of the License, or (at your option) any later version.
16  *
17  * This library is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * Library General Public License for more details.
21  *
22  * You should have received a copy of the GNU Library General Public License
23  * along with this library; see the file COPYING.LIB.  If not, write to
24  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
25  * Boston, MA 02111-1307, USA.
26  */
27
28 #include "config.h"
29 #include "Frame.h"
30 #include "FramePrivate.h"
31
32 #include "ApplyStyleCommand.h"
33 #include "CSSComputedStyleDeclaration.h"
34 #include "CSSProperty.h"
35 #include "CSSPropertyNames.h"
36 #include "Cache.h"
37 #include "CachedCSSStyleSheet.h"
38 #include "DOMImplementation.h"
39 #include "DOMWindow.h"
40 #include "Decoder.h"
41 #include "DocLoader.h"
42 #include "DocumentType.h"
43 #include "EditingText.h"
44 #include "Event.h"
45 #include "EventNames.h"
46 #include "FloatRect.h"
47 #include "Frame.h"
48 #include "GraphicsContext.h"
49 #include "HTMLFormElement.h"
50 #include "HTMLFrameElement.h"
51 #include "HTMLGenericFormElement.h"
52 #include "HTMLInputElement.h"
53 #include "HTMLNames.h"
54 #include "HTMLObjectElement.h"
55 #include "HTMLViewSourceDocument.h"
56 #include "ImageDocument.h"
57 #include "MediaFeatureNames.h"
58 #include "MouseEventWithHitTestResults.h"
59 #include "NodeList.h"
60 #include "Page.h"
61 #include "PlatformScrollBar.h"
62 #include "PlugInInfoStore.h"
63 #include "Plugin.h"
64 #include "PluginDocument.h"
65 #include "RenderPart.h"
66 #include "RenderTextControl.h"
67 #include "RenderTheme.h"
68 #include "RenderView.h"
69 #include "SegmentedString.h"
70 #include "TextDocument.h"
71 #include "TextIterator.h"
72 #include "TypingCommand.h"
73 #include "XMLTokenizer.h"
74 #include "cssstyleselector.h"
75 #include "htmlediting.h"
76 #include "kjs_window.h"
77 #include "markup.h"
78 #include "visible_units.h"
79 #include "xmlhttprequest.h"
80 #include <math.h>
81 #include <sys/types.h>
82 #include <wtf/Platform.h>
83
84 #if !PLATFORM(WIN_OS)
85 #include <unistd.h>
86 #endif
87
88 #ifdef SVG_SUPPORT
89 #include "SVGNames.h"
90 #include "XLinkNames.h"
91 #include "XMLNames.h"
92 #include "SVGDocument.h"
93 #include "SVGDocumentExtensions.h"
94 #endif
95
96 using namespace std;
97
98 using KJS::JSLock;
99 using KJS::JSValue;
100 using KJS::Location;
101 using KJS::PausedTimeouts;
102 using KJS::SavedProperties;
103 using KJS::SavedBuiltins;
104 using KJS::UString;
105 using KJS::Window;
106
107 namespace WebCore {
108
109 using namespace EventNames;
110 using namespace HTMLNames;
111
112 const double caretBlinkFrequency = 0.5;
113 const double autoscrollInterval = 0.1;
114
115 class UserStyleSheetLoader : public CachedResourceClient {
116 public:
117     UserStyleSheetLoader(Frame* frame, const String& url, DocLoader* dl)
118         : m_frame(frame)
119         , m_cachedSheet(Cache::requestStyleSheet(dl, url, false, 0, ""))
120     {
121         m_cachedSheet->ref(this);
122     }
123     ~UserStyleSheetLoader()
124     {
125         m_cachedSheet->deref(this);
126     }
127 private:
128     virtual void setStyleSheet(const String& /*URL*/, const String& sheet)
129     {
130         m_frame->setUserStyleSheet(sheet.deprecatedString());
131     }
132     Frame* m_frame;
133     CachedCSSStyleSheet* m_cachedSheet;
134 };
135
136 #ifndef NDEBUG
137 struct FrameCounter { 
138     static int count; 
139     ~FrameCounter() { if (count != 0) fprintf(stderr, "LEAK: %d Frame\n", count); }
140 };
141 int FrameCounter::count = 0;
142 static FrameCounter frameCounter;
143 #endif
144
145 static inline Frame* parentFromOwnerElement(Element* ownerElement)
146 {
147     if (!ownerElement)
148         return 0;
149     return ownerElement->document()->frame();
150 }
151
152 Frame::Frame(Page* page, Element* ownerElement) 
153     : d(new FramePrivate(page, parentFromOwnerElement(ownerElement), this, ownerElement))
154 {
155     AtomicString::init();
156     Cache::init();
157     EventNames::init();
158     HTMLNames::init();
159     QualifiedName::init();
160     MediaFeatureNames::init();
161
162 #ifdef SVG_SUPPORT
163     SVGNames::init();
164     XLinkNames::init();
165     XMLNames::init();
166 #endif
167
168     if (d->m_ownerElement)
169         d->m_page->incrementFrameCount();
170
171     // FIXME: Frames were originally created with a refcount of 1, leave this
172     // ref call here until we can straighten that out.
173     ref();
174 #ifndef NDEBUG
175     ++FrameCounter::count;
176 #endif
177 }
178
179 Frame::~Frame()
180 {
181     ASSERT(!d->m_lifeSupportTimer.isActive());
182
183 #ifndef NDEBUG
184     --FrameCounter::count;
185 #endif
186
187     cancelRedirection();
188
189     if (!d->m_bComplete)
190         closeURL();
191
192     clear(false);
193
194     if (d->m_jscript && d->m_jscript->haveInterpreter())
195         if (Window* w = Window::retrieveWindow(this)) {
196             w->disconnectFrame();
197             // Must clear the window pointer, otherwise we will not
198             // garbage-collect collect the window (inside the call to
199             // delete d below).
200             w = 0;
201         }
202
203     disconnectOwnerElement();
204     
205     if (d->m_domWindow)
206         d->m_domWindow->disconnectFrame();
207             
208     setOpener(0);
209     HashSet<Frame*> openedBy = d->m_openedFrames;
210     HashSet<Frame*>::iterator end = openedBy.end();
211     for (HashSet<Frame*>::iterator it = openedBy.begin(); it != end; ++it)
212         (*it)->setOpener(0);
213     
214     if (d->m_view) {
215         d->m_view->hide();
216         d->m_view->m_frame = 0;
217     }
218   
219     ASSERT(!d->m_lifeSupportTimer.isActive());
220
221     delete d->m_userStyleSheetLoader;
222     delete d;
223     d = 0;
224 }
225
226 bool Frame::didOpenURL(const KURL& url)
227 {
228   if (d->m_scheduledRedirection == locationChangeScheduledDuringLoad) {
229     // A redirect was shceduled before the document was created. This can happen
230     // when one frame changes another frame's location.
231     return false;
232   }
233   
234   cancelRedirection();
235   
236   // clear last edit command
237   d->m_lastEditCommand = EditCommandPtr();
238   
239   closeURL();
240
241   d->m_bComplete = false;
242   d->m_bLoadingMainResource = true;
243   d->m_bLoadEventEmitted = false;
244
245   d->m_kjsStatusBarText = String();
246   d->m_kjsDefaultStatusBarText = String();
247
248   d->m_bJScriptEnabled = d->m_settings->isJavaScriptEnabled();
249   d->m_bJavaEnabled = d->m_settings->isJavaEnabled();
250   d->m_bPluginsEnabled = d->m_settings->isPluginsEnabled();
251
252   // initializing d->m_url to the new url breaks relative links when opening such a link after this call and _before_ begin() is called (when the first
253   // data arrives) (Simon)
254   d->m_url = url;
255   if (d->m_url.protocol().startsWith("http") && !d->m_url.host().isEmpty() && d->m_url.path().isEmpty())
256     d->m_url.setPath("/");
257   d->m_workingURL = d->m_url;
258
259   started();
260
261   return true;
262 }
263
264 void Frame::didExplicitOpen()
265 {
266   d->m_bComplete = false;
267   d->m_bLoadEventEmitted = false;
268     
269   // Prevent window.open(url) -- eg window.open("about:blank") -- from blowing away results
270   // from a subsequent window.document.open / window.document.write call. 
271   // Cancelling redirection here works for all cases because document.open 
272   // implicitly precedes document.write.
273   cancelRedirection(); 
274 }
275
276 void Frame::stopLoading(bool sendUnload)
277 {
278   if (d->m_doc && d->m_doc->tokenizer())
279     d->m_doc->tokenizer()->stopParsing();
280   
281   d->m_metaData.clear();
282
283   if (sendUnload) {
284     if (d->m_doc) {
285       if (d->m_bLoadEventEmitted && !d->m_bUnloadEventEmitted) {
286         Node* currentFocusNode = d->m_doc->focusNode();
287         if (currentFocusNode)
288             currentFocusNode->aboutToUnload();
289         d->m_doc->dispatchWindowEvent(unloadEvent, false, false);
290         if (d->m_doc)
291           d->m_doc->updateRendering();
292         d->m_bUnloadEventEmitted = true;
293       }
294     }
295     
296     if (d->m_doc && !d->m_doc->inPageCache())
297       d->m_doc->removeAllEventListenersFromAllNodes();
298   }
299
300   d->m_bComplete = true; // to avoid calling completed() in finishedParsing() (David)
301   d->m_bLoadingMainResource = false;
302   d->m_bLoadEventEmitted = true; // don't want that one either
303   d->m_cachePolicy = CachePolicyVerify; // Why here?
304
305   if (d->m_doc && d->m_doc->parsing()) {
306     finishedParsing();
307     d->m_doc->setParsing(false);
308   }
309   
310   d->m_workingURL = KURL();
311
312   if (Document *doc = d->m_doc.get()) {
313     if (DocLoader *docLoader = doc->docLoader())
314       Cache::loader()->cancelRequests(docLoader);
315       XMLHttpRequest::cancelRequests(doc);
316   }
317
318   // tell all subframes to stop as well
319   for (Frame* child = tree()->firstChild(); child; child = child->tree()->nextSibling())
320       child->stopLoading(sendUnload);
321
322   d->m_bPendingChildRedirection = false;
323
324   cancelRedirection();
325 }
326
327 BrowserExtension *Frame::browserExtension() const
328 {
329   return d->m_extension;
330 }
331
332 FrameView* Frame::view() const
333 {
334     return d->m_view.get();
335 }
336
337 void Frame::setView(FrameView* view)
338 {
339     d->m_view = view;
340 }
341
342 bool Frame::jScriptEnabled() const
343 {
344     return d->m_bJScriptEnabled;
345 }
346
347 KJSProxy *Frame::jScript()
348 {
349     if (!d->m_bJScriptEnabled)
350         return 0;
351
352     if (!d->m_jscript)
353         d->m_jscript = new KJSProxy(this);
354
355     return d->m_jscript;
356 }
357
358 static bool getString(JSValue* result, DeprecatedString& string)
359 {
360     if (!result)
361         return false;
362     JSLock lock;
363     UString ustring;
364     if (!result->getString(ustring))
365         return false;
366     string = ustring;
367     return true;
368 }
369
370 void Frame::replaceContentsWithScriptResult(const KURL& url)
371 {
372     JSValue* ret = executeScript(0, KURL::decode_string(url.url().mid(strlen("javascript:"))));
373     DeprecatedString scriptResult;
374     if (getString(ret, scriptResult)) {
375         begin();
376         write(scriptResult);
377         end();
378     }
379 }
380
381 JSValue* Frame::executeScript(Node* n, const DeprecatedString& script, bool forceUserGesture)
382 {
383   KJSProxy *proxy = jScript();
384
385   if (!proxy)
386     return 0;
387
388   d->m_runningScripts++;
389   // If forceUserGesture is true, then make the script interpreter
390   // treat it as if triggered by a user gesture even if there is no
391   // current DOM event being processed.
392   JSValue* ret = proxy->evaluate(forceUserGesture ? DeprecatedString::null : d->m_url.url(), 0, script, n);
393   d->m_runningScripts--;
394
395   if (!d->m_runningScripts)
396       submitFormAgain();
397
398   Document::updateDocumentsRendering();
399
400   return ret;
401 }
402
403 bool Frame::javaEnabled() const
404 {
405     return d->m_settings->isJavaEnabled();
406 }
407
408 bool Frame::pluginsEnabled() const
409 {
410     return d->m_bPluginsEnabled;
411 }
412
413 void Frame::setAutoloadImages(bool enable)
414 {
415   if (d->m_doc && d->m_doc->docLoader()->autoloadImages() == enable)
416     return;
417
418   if (d->m_doc)
419     d->m_doc->docLoader()->setAutoloadImages(enable);
420 }
421
422 bool Frame::autoloadImages() const
423 {
424   if (d->m_doc)
425     return d->m_doc->docLoader()->autoloadImages();
426
427   return true;
428 }
429
430 void Frame::clear(bool clearWindowProperties)
431 {
432   if (d->m_bCleared)
433     return;
434   d->m_bCleared = true;
435   d->m_mousePressNode = 0;
436
437   if (d->m_doc) {
438     d->m_doc->cancelParsing();
439     d->m_doc->detach();
440   }
441
442   // Moving past doc so that onUnload works.
443   if (clearWindowProperties && d->m_jscript)
444     d->m_jscript->clear();
445
446   if (d->m_view)
447     d->m_view->clear();
448
449   // do not drop the document before the jscript and view are cleared, as some destructors
450   // might still try to access the document.
451   d->m_doc = 0;
452   d->m_decoder = 0;
453
454   d->m_plugins.clear();
455
456   d->m_scheduledRedirection = noRedirectionScheduled;
457   d->m_delayRedirect = 0;
458   d->m_redirectURL = DeprecatedString::null;
459   d->m_redirectReferrer = DeprecatedString::null;
460   d->m_redirectLockHistory = true;
461   d->m_redirectUserGesture = false;
462   d->m_bHTTPRefresh = false;
463   d->m_bFirstData = true;
464
465   d->m_bMousePressed = false;
466
467   if (!d->m_haveEncoding)
468     d->m_encoding = DeprecatedString::null;
469 }
470
471 Document *Frame::document() const
472 {
473     if (d)
474         return d->m_doc.get();
475     return 0;
476 }
477
478 void Frame::setDocument(Document* newDoc)
479 {
480     if (d) {
481         if (d->m_doc)
482             d->m_doc->detach();
483         d->m_doc = newDoc;
484         if (newDoc)
485             newDoc->attach();
486     }
487 }
488
489 void Frame::receivedFirstData()
490 {
491     begin(d->m_workingURL);
492
493     d->m_doc->docLoader()->setCachePolicy(d->m_cachePolicy);
494     d->m_workingURL = KURL();
495
496     // When the first data arrives, the metadata has just been made available
497     DeprecatedString qData;
498
499     // Support for http-refresh
500     qData = d->m_metaData.get("http-refresh").deprecatedString();
501     if (!qData.isEmpty()) {
502       double delay;
503       int pos = qData.find(';');
504       if (pos == -1)
505         pos = qData.find(',');
506
507       if (pos == -1) {
508         delay = qData.stripWhiteSpace().toDouble();
509         // We want a new history item if the refresh timeout > 1 second
510         scheduleRedirection(delay, d->m_url.url(), delay <= 1);
511       } else {
512         int end_pos = qData.length();
513         delay = qData.left(pos).stripWhiteSpace().toDouble();
514         while (qData[++pos] == ' ');
515         if (qData.find("url", pos, false) == pos) {
516           pos += 3;
517           while (qData[pos] == ' ' || qData[pos] == '=')
518               pos++;
519           if (qData[pos] == '"') {
520               pos++;
521               int index = end_pos-1;
522               while (index > pos) {
523                 if (qData[index] == '"')
524                     break;
525                 index--;
526               }
527               if (index > pos)
528                 end_pos = index;
529           }
530         }
531         // We want a new history item if the refresh timeout > 1 second
532         scheduleRedirection(delay, d->m_doc->completeURL(qData.mid(pos, end_pos)), delay <= 1);
533       }
534       d->m_bHTTPRefresh = true;
535     }
536
537     // Support for http last-modified
538     d->m_lastModified = d->m_metaData.get("modified");
539 }
540
541 void Frame::childBegin()
542 {
543     // We need to do this when the child is created so as to avoid the parent thining the child
544     // is complete before it has even started loading.
545     // FIXME: do we really still need this?
546     d->m_bComplete = false;
547 }
548
549 void Frame::setResourceRequest(const ResourceRequest& request)
550 {
551     d->m_request = request;
552 }
553
554 const ResourceRequest& Frame::resourceRequest() const
555 {
556     return d->m_request;
557 }
558
559 void Frame::begin(const KURL& url)
560 {
561   if (d->m_workingURL.isEmpty())
562     createEmptyDocument(); // Creates an empty document if we don't have one already
563
564   clear();
565   partClearedInBegin();
566
567   d->m_bCleared = false;
568   d->m_bComplete = false;
569   d->m_bLoadEventEmitted = false;
570   d->m_bLoadingMainResource = true;
571
572   KURL ref(url);
573   ref.setUser(DeprecatedString());
574   ref.setPass(DeprecatedString());
575   ref.setRef(DeprecatedString());
576   d->m_referrer = ref.url();
577   d->m_url = url;
578   KURL baseurl;
579
580   // We don't need KDE chained URI handling or window caption setting
581   if (!d->m_url.isEmpty())
582     baseurl = d->m_url;
583
584 #ifdef SVG_SUPPORT
585   if (d->m_request.m_responseMIMEType == "image/svg+xml")
586     d->m_doc = DOMImplementation::instance()->createSVGDocument(d->m_view.get());
587   else
588 #endif
589   if (DOMImplementation::isXMLMIMEType(d->m_request.m_responseMIMEType))
590     d->m_doc = DOMImplementation::instance()->createDocument(d->m_view.get());
591   else if (DOMImplementation::isTextMIMEType(d->m_request.m_responseMIMEType))
592     d->m_doc = new TextDocument(DOMImplementation::instance(), d->m_view.get());
593   else if ((d->m_request.m_responseMIMEType == "application/pdf" || d->m_request.m_responseMIMEType == "text/pdf") && PlugInInfoStore::supportsMIMEType(d->m_request.m_responseMIMEType))
594     d->m_doc = new PluginDocument(DOMImplementation::instance(), d->m_view.get());
595   else if (Image::supportsType(d->m_request.m_responseMIMEType))
596     d->m_doc = new ImageDocument(DOMImplementation::instance(), d->m_view.get());
597   else if (PlugInInfoStore::supportsMIMEType(d->m_request.m_responseMIMEType))
598     d->m_doc = new PluginDocument(DOMImplementation::instance(), d->m_view.get());
599   else if (inViewSourceMode())
600     d->m_doc = new HTMLViewSourceDocument(DOMImplementation::instance(), d->m_view.get());
601   else
602     d->m_doc = DOMImplementation::instance()->createHTMLDocument(d->m_view.get());
603
604   if (!d->m_doc->attached())
605     d->m_doc->attach();
606   d->m_doc->setURL(d->m_url.url());
607   // We prefer m_baseURL over d->m_url because d->m_url changes when we are
608   // about to load a new page.
609   d->m_doc->setBaseURL(baseurl.url());
610   if (d->m_decoder)
611     d->m_doc->setDecoder(d->m_decoder.get());
612
613   updatePolicyBaseURL();
614
615   setAutoloadImages(d->m_settings->autoLoadImages());
616   const KURL& userStyleSheet = d->m_settings->userStyleSheetLocation();
617
618   if (!userStyleSheet.isEmpty())
619     setUserStyleSheetLocation(KURL(userStyleSheet));
620
621   restoreDocumentState();
622
623   d->m_doc->implicitOpen();
624   // clear widget
625   if (d->m_view)
626     d->m_view->resizeContents(0, 0);
627 }
628
629 void Frame::write(const char* str, int len)
630 {
631     if (len == 0)
632         return;
633     
634     if (len == -1)
635         len = strlen(str);
636
637     if (Tokenizer* t = d->m_doc->tokenizer()) {
638         if (t->wantsRawData()) {
639             t->writeRawData(str, len);
640             return;
641         }
642     }
643     
644     if (!d->m_decoder) {
645         d->m_decoder = new Decoder;
646         if (!d->m_encoding.isNull())
647             d->m_decoder->setEncodingName(d->m_encoding.latin1(),
648                 d->m_haveEncoding ? Decoder::UserChosenEncoding : Decoder::EncodingFromHTTPHeader);
649         else
650             d->m_decoder->setEncodingName(settings()->encoding().latin1(), Decoder::DefaultEncoding);
651
652         if (d->m_doc)
653             d->m_doc->setDecoder(d->m_decoder.get());
654     }
655   DeprecatedString decoded = d->m_decoder->decode(str, len);
656
657   if (decoded.isEmpty())
658     return;
659
660   if (d->m_bFirstData) {
661       // determine the parse mode
662       d->m_doc->determineParseMode(decoded);
663       d->m_bFirstData = false;
664
665       // ### this is still quite hacky, but should work a lot better than the old solution
666       if (d->m_decoder->visuallyOrdered()) d->m_doc->setVisuallyOrdered();
667       d->m_doc->recalcStyle(Node::Force);
668   }
669
670   if (Tokenizer* t = d->m_doc->tokenizer()) {
671       ASSERT(!t->wantsRawData());
672       t->write(decoded, true);
673   }
674 }
675
676 void Frame::write(const DeprecatedString& str)
677 {
678   if (str.isNull())
679     return;
680
681   if (d->m_bFirstData) {
682       // determine the parse mode
683       d->m_doc->setParseMode(Document::Strict);
684       d->m_bFirstData = false;
685   }
686   Tokenizer* t = d->m_doc->tokenizer();
687   if (t)
688     t->write(str, true);
689 }
690
691 void Frame::end()
692 {
693     d->m_bLoadingMainResource = false;
694     endIfNotLoading();
695 }
696
697 void Frame::endIfNotLoading()
698 {
699     if (d->m_bLoadingMainResource)
700         return;
701
702     // make sure nothing's left in there...
703     if (d->m_doc) {
704         if (d->m_decoder) {
705             DeprecatedString decoded = d->m_decoder->flush();
706             if (d->m_bFirstData) {
707                 d->m_doc->determineParseMode(decoded);
708                 d->m_bFirstData = false;
709             }
710             write(decoded);
711         }
712         d->m_doc->finishParsing();
713     } else
714         // WebKit partially uses WebCore when loading non-HTML docs.  In these cases doc==nil, but
715         // WebCore is enough involved that we need to checkCompleted() in order for m_bComplete to
716         // become true.  An example is when a subframe is a pure text doc, and that subframe is the
717         // last one to complete.
718         checkCompleted();
719 }
720
721 void Frame::stop()
722 {
723     if (d->m_doc) {
724         if (d->m_doc->tokenizer())
725             d->m_doc->tokenizer()->stopParsing();
726         d->m_doc->finishParsing();
727     } else
728         // WebKit partially uses WebCore when loading non-HTML docs.  In these cases doc==nil, but
729         // WebCore is enough involved that we need to checkCompleted() in order for m_bComplete to
730         // become true.  An example is when a subframe is a pure text doc, and that subframe is the
731         // last one to complete.
732         checkCompleted();
733 }
734
735 void Frame::gotoAnchor()
736 {
737     // If our URL has no ref, then we have no place we need to jump to.
738     if (!d->m_url.hasRef())
739         return;
740
741     DeprecatedString ref = d->m_url.encodedHtmlRef();
742     if (!gotoAnchor(ref)) {
743         // Can't use htmlRef() here because it doesn't know which encoding to use to decode.
744         // Decoding here has to match encoding in completeURL, which means it has to use the
745         // page's encoding rather than UTF-8.
746         if (d->m_decoder)
747             gotoAnchor(KURL::decode_string(ref, d->m_decoder->encoding()));
748     }
749 }
750
751 void Frame::finishedParsing()
752 {
753   RefPtr<Frame> protector(this);
754   checkCompleted();
755
756   if (!d->m_view)
757     return; // We are being destroyed by something checkCompleted called.
758
759   // check if the scrollbars are really needed for the content
760   // if not, remove them, relayout, and repaint
761
762   d->m_view->restoreScrollBar();
763   gotoAnchor();
764 }
765
766 void Frame::loadDone()
767 {
768     if (d->m_doc)
769         checkCompleted();
770 }
771
772 void Frame::checkCompleted()
773 {
774   // Any frame that hasn't completed yet ?
775   for (Frame* child = tree()->firstChild(); child; child = child->tree()->nextSibling())
776       if (!child->d->m_bComplete)
777           return;
778
779   // Have we completed before?
780   if (d->m_bComplete)
781       return;
782
783   // Are we still parsing?
784   if (d->m_doc && d->m_doc->parsing())
785       return;
786
787   // Still waiting for images/scripts from the loader ?
788   int requests = 0;
789   if (d->m_doc && d->m_doc->docLoader())
790       requests = Cache::loader()->numRequests(d->m_doc->docLoader());
791
792   if (requests > 0)
793       return;
794
795   // OK, completed.
796   // Now do what should be done when we are really completed.
797   d->m_bComplete = true;
798
799   checkEmitLoadEvent(); // if we didn't do it before
800
801   if (d->m_scheduledRedirection != noRedirectionScheduled) {
802       // Do not start redirection for frames here! That action is
803       // deferred until the parent emits a completed signal.
804       if (!tree()->parent())
805           startRedirectionTimer();
806
807       completed(true);
808   } else {
809       completed(d->m_bPendingChildRedirection);
810   }
811 }
812
813 void Frame::checkEmitLoadEvent()
814 {
815     if (d->m_bLoadEventEmitted || !d->m_doc || d->m_doc->parsing())
816         return;
817
818     for (Frame* child = tree()->firstChild(); child; child = child->tree()->nextSibling())
819         if (!child->d->m_bComplete) // still got a frame running -> too early
820             return;
821
822     // All frames completed -> set their domain to the frameset's domain
823     // This must only be done when loading the frameset initially (#22039),
824     // not when following a link in a frame (#44162).
825     if (d->m_doc) {
826         String domain = d->m_doc->domain();
827         for (Frame* child = tree()->firstChild(); child; child = child->tree()->nextSibling())
828             if (child->d->m_doc)
829                 child->d->m_doc->setDomain(domain);
830     }
831
832     d->m_bLoadEventEmitted = true;
833     d->m_bUnloadEventEmitted = false;
834     if (d->m_doc)
835         d->m_doc->implicitClose();
836 }
837
838 const Settings *Frame::settings() const
839 {
840   return d->m_settings;
841 }
842
843 KURL Frame::baseURL() const
844 {
845     if (!d->m_doc)
846         return KURL();
847     return d->m_doc->baseURL();
848 }
849
850 String Frame::baseTarget() const
851 {
852     if (!d->m_doc)
853         return DeprecatedString();
854     return d->m_doc->baseTarget();
855 }
856
857 KURL Frame::completeURL(const DeprecatedString& url)
858 {
859     if (!d->m_doc)
860         return url;
861
862     return KURL(d->m_doc->completeURL(url));
863 }
864
865 void Frame::scheduleRedirection(double delay, const DeprecatedString& url, bool doLockHistory)
866 {
867     if (delay < 0 || delay > INT_MAX / 1000)
868       return;
869     if (d->m_scheduledRedirection == noRedirectionScheduled || delay <= d->m_delayRedirect)
870     {
871        d->m_scheduledRedirection = redirectionScheduled;
872        d->m_delayRedirect = delay;
873        d->m_redirectURL = url;
874        d->m_redirectReferrer = DeprecatedString::null;
875        d->m_redirectLockHistory = doLockHistory;
876        d->m_redirectUserGesture = false;
877
878        stopRedirectionTimer();
879        if (d->m_bComplete)
880          startRedirectionTimer();
881     }
882 }
883
884 void Frame::scheduleLocationChange(const DeprecatedString& url, const DeprecatedString& referrer, bool lockHistory, bool userGesture)
885 {
886     KURL u(url);
887     
888     // If the URL we're going to navigate to is the same as the current one, except for the
889     // fragment part, we don't need to schedule the location change.
890     if (u.hasRef() && equalIgnoringRef(d->m_url, u)) {
891         changeLocation(url, referrer, lockHistory, userGesture);
892         return;
893     }
894         
895     // Handle a location change of a page with no document as a special case.
896     // This may happen when a frame changes the location of another frame.
897     d->m_scheduledRedirection = d->m_doc ? locationChangeScheduled : locationChangeScheduledDuringLoad;
898     
899     // If a redirect was scheduled during a load, then stop the current load.
900     // Otherwise when the current load transitions from a provisional to a 
901     // committed state, pending redirects may be cancelled. 
902     if (d->m_scheduledRedirection == locationChangeScheduledDuringLoad) {
903         stopLoading(true);   
904     }
905
906     d->m_delayRedirect = 0;
907     d->m_redirectURL = url;
908     d->m_redirectReferrer = referrer;
909     d->m_redirectLockHistory = lockHistory;
910     d->m_redirectUserGesture = userGesture;
911     stopRedirectionTimer();
912     if (d->m_bComplete)
913         startRedirectionTimer();
914 }
915
916 void Frame::scheduleRefresh(bool userGesture)
917 {
918     // Handle a location change of a page with no document as a special case.
919     // This may happen when a frame requests a refresh of another frame.
920     d->m_scheduledRedirection = d->m_doc ? locationChangeScheduled : locationChangeScheduledDuringLoad;
921     
922     // If a refresh was scheduled during a load, then stop the current load.
923     // Otherwise when the current load transitions from a provisional to a 
924     // committed state, pending redirects may be cancelled. 
925     if (d->m_scheduledRedirection == locationChangeScheduledDuringLoad)
926         stopLoading(true);   
927
928     d->m_delayRedirect = 0;
929     d->m_redirectURL = url().url();
930     d->m_redirectReferrer = referrer();
931     d->m_redirectLockHistory = true;
932     d->m_redirectUserGesture = userGesture;
933     d->m_cachePolicy = CachePolicyRefresh;
934     stopRedirectionTimer();
935     if (d->m_bComplete)
936         startRedirectionTimer();
937 }
938
939 bool Frame::isScheduledLocationChangePending() const
940 {
941     switch (d->m_scheduledRedirection) {
942         case noRedirectionScheduled:
943         case redirectionScheduled:
944             return false;
945         case historyNavigationScheduled:
946         case locationChangeScheduled:
947         case locationChangeScheduledDuringLoad:
948             return true;
949     }
950     return false;
951 }
952
953 void Frame::scheduleHistoryNavigation(int steps)
954 {
955     // navigation will always be allowed in the 0 steps case, which is OK because
956     // that's supposed to force a reload.
957     if (!canGoBackOrForward(steps)) {
958         cancelRedirection();
959         return;
960     }
961
962     // If the URL we're going to navigate to is the same as the current one, except for the
963     // fragment part, we don't need to schedule the navigation.
964     if (d->m_extension) {
965         KURL u = d->m_extension->historyURL(steps);
966         
967         if (equalIgnoringRef(d->m_url, u)) {
968             d->m_extension->goBackOrForward(steps);
969             return;
970         }
971     }
972     
973     d->m_scheduledRedirection = historyNavigationScheduled;
974     d->m_delayRedirect = 0;
975     d->m_redirectURL = DeprecatedString::null;
976     d->m_redirectReferrer = DeprecatedString::null;
977     d->m_scheduledHistoryNavigationSteps = steps;
978     stopRedirectionTimer();
979     if (d->m_bComplete)
980         startRedirectionTimer();
981 }
982
983 void Frame::cancelRedirection(bool cancelWithLoadInProgress)
984 {
985     if (d) {
986         d->m_cancelWithLoadInProgress = cancelWithLoadInProgress;
987         d->m_scheduledRedirection = noRedirectionScheduled;
988         stopRedirectionTimer();
989     }
990 }
991
992 void Frame::changeLocation(const DeprecatedString& URL, const DeprecatedString& referrer, bool lockHistory, bool userGesture)
993 {
994     if (URL.find("javascript:", 0, false) == 0) {
995         DeprecatedString script = KURL::decode_string(URL.mid(11));
996         JSValue* result = executeScript(0, script, userGesture);
997         DeprecatedString scriptResult;
998         if (getString(result, scriptResult)) {
999             begin(url());
1000             write(scriptResult);
1001             end();
1002         }
1003         return;
1004     }
1005
1006     ResourceRequest request(completeURL(URL));
1007     request.setLockHistory(lockHistory);
1008     if (!referrer.isEmpty())
1009         request.setReferrer(referrer);
1010
1011     request.reload = (d->m_cachePolicy == CachePolicyReload) || (d->m_cachePolicy == CachePolicyRefresh);
1012     
1013     urlSelected(request, "_self");
1014 }
1015
1016 void Frame::redirectionTimerFired(Timer<Frame>*)
1017 {
1018     if (d->m_scheduledRedirection == historyNavigationScheduled) {
1019         d->m_scheduledRedirection = noRedirectionScheduled;
1020
1021         // Special case for go(0) from a frame -> reload only the frame
1022         // go(i!=0) from a frame navigates into the history of the frame only,
1023         // in both IE and NS (but not in Mozilla).... we can't easily do that
1024         // in Konqueror...
1025         if (d->m_scheduledHistoryNavigationSteps == 0) // add && parent() to get only frames, but doesn't matter
1026             openURL(url()); /// ## need args.reload=true?
1027         else {
1028             if (d->m_extension) {
1029                 d->m_extension->goBackOrForward(d->m_scheduledHistoryNavigationSteps);
1030             }
1031         }
1032         return;
1033     }
1034
1035     DeprecatedString URL = d->m_redirectURL;
1036     DeprecatedString referrer = d->m_redirectReferrer;
1037     bool lockHistory = d->m_redirectLockHistory;
1038     bool userGesture = d->m_redirectUserGesture;
1039
1040     d->m_scheduledRedirection = noRedirectionScheduled;
1041     d->m_delayRedirect = 0;
1042     d->m_redirectURL = DeprecatedString::null;
1043     d->m_redirectReferrer = DeprecatedString::null;
1044
1045     changeLocation(URL, referrer, lockHistory, userGesture);
1046 }
1047
1048 DeprecatedString Frame::encoding() const
1049 {
1050     if (d->m_haveEncoding && !d->m_encoding.isEmpty())
1051         return d->m_encoding;
1052
1053     if (d->m_decoder && d->m_decoder->encoding().isValid())
1054         return d->m_decoder->encodingName();
1055
1056     return settings()->encoding();
1057 }
1058
1059 void Frame::setUserStyleSheetLocation(const KURL& url)
1060 {
1061     delete d->m_userStyleSheetLoader;
1062     d->m_userStyleSheetLoader = 0;
1063     if (d->m_doc && d->m_doc->docLoader())
1064         d->m_userStyleSheetLoader = new UserStyleSheetLoader(this, url.url(), d->m_doc->docLoader());
1065 }
1066
1067 void Frame::setUserStyleSheet(const String& styleSheet)
1068 {
1069     delete d->m_userStyleSheetLoader;
1070     d->m_userStyleSheetLoader = 0;
1071     if (d->m_doc)
1072         d->m_doc->setUserStyleSheet(styleSheet);
1073 }
1074
1075 bool Frame::gotoAnchor(const String& name)
1076 {
1077   if (!d->m_doc)
1078     return false;
1079
1080   Node *n = d->m_doc->getElementById(AtomicString(name));
1081   if (!n)
1082       n = d->m_doc->anchors()->namedItem(name, !d->m_doc->inCompatMode());
1083
1084   d->m_doc->setCSSTarget(n); // Setting to null will clear the current target.
1085   
1086   // Implement the rule that "" and "top" both mean top of page as in other browsers.
1087   if (!n && !(name.isEmpty() || name.lower() == "top"))
1088       return false;
1089
1090   // We need to update the layout before scrolling, otherwise we could
1091   // really mess things up if an anchor scroll comes at a bad moment.
1092   if (d->m_doc) {
1093     d->m_doc->updateRendering();
1094     // Only do a layout if changes have occurred that make it necessary.      
1095     if (d->m_view && d->m_doc->renderer() && d->m_doc->renderer()->needsLayout()) {
1096       d->m_view->layout();
1097     }
1098   }
1099   
1100   // Scroll nested layers and frames to reveal the anchor.
1101   RenderObject *renderer;
1102   IntRect rect;
1103   if (n) {
1104       renderer = n->renderer();
1105       rect = n->getRect();
1106   } else {
1107     // If there's no node, we should scroll to the top of the document.
1108       renderer = d->m_doc->renderer();
1109       rect = IntRect();
1110   }
1111
1112   if (renderer) {
1113     // Align to the top and to the closest side (this matches other browsers).
1114     renderer->enclosingLayer()->scrollRectToVisible(rect, RenderLayer::gAlignToEdgeIfNeeded, RenderLayer::gAlignTopAlways);
1115   }
1116   
1117   return true;
1118 }
1119
1120 void Frame::setStandardFont(const String& name)
1121 {
1122     d->m_settings->setStdFontName(AtomicString(name));
1123 }
1124
1125 void Frame::setFixedFont(const String& name)
1126 {
1127     d->m_settings->setFixedFontName(AtomicString(name));
1128 }
1129
1130 String Frame::selectedText() const
1131 {
1132     return plainText(selection().toRange().get());
1133 }
1134
1135 bool Frame::hasSelection() const
1136 {
1137     return d->m_selection.isCaretOrRange();
1138 }
1139
1140 SelectionController& Frame::selection() const
1141 {
1142     return d->m_selection;
1143 }
1144
1145 TextGranularity Frame::selectionGranularity() const
1146 {
1147     return d->m_selectionGranularity;
1148 }
1149
1150 void Frame::setSelectionGranularity(TextGranularity granularity) const
1151 {
1152     d->m_selectionGranularity = granularity;
1153 }
1154
1155 SelectionController& Frame::dragCaret() const
1156 {
1157     return d->m_page->dragCaret();
1158 }
1159
1160 const Selection& Frame::mark() const
1161 {
1162     return d->m_mark;
1163 }
1164
1165 void Frame::setMark(const Selection& s)
1166 {
1167     ASSERT(!s.base().node() || s.base().node()->document() == document());
1168     ASSERT(!s.extent().node() || s.extent().node()->document() == document());
1169     ASSERT(!s.start().node() || s.start().node()->document() == document());
1170     ASSERT(!s.end().node() || s.end().node()->document() == document());
1171
1172     d->m_mark = s;
1173 }
1174
1175 void Frame::setSelection(const SelectionController& s, bool closeTyping)
1176 {
1177     if (closeTyping)
1178         TypingCommand::closeTyping(lastEditCommand());
1179
1180     clearTypingStyle();
1181         
1182     if (d->m_selection == s)
1183         return;
1184     
1185     ASSERT(!s.base().node() || s.base().node()->document() == document());
1186     ASSERT(!s.extent().node() || s.extent().node()->document() == document());
1187     ASSERT(!s.start().node() || s.start().node()->document() == document());
1188     ASSERT(!s.end().node() || s.end().node()->document() == document());
1189     
1190     clearCaretRectIfNeeded();
1191
1192     SelectionController oldSelection = d->m_selection;
1193
1194     d->m_selection = s;
1195     if (!s.isNone())
1196         setFocusNodeIfNeeded();
1197     
1198     selectionLayoutChanged();
1199
1200     // Always clear the x position used for vertical arrow navigation.
1201     // It will be restored by the vertical arrow navigation code if necessary.
1202     d->m_xPosForVerticalArrowNavigation = NoXPosForVerticalArrowNavigation;
1203     
1204     notifyRendererOfSelectionChange(false);
1205
1206     respondToChangedSelection(oldSelection, closeTyping);
1207 }
1208
1209 void Frame::notifyRendererOfSelectionChange(bool userTriggered)
1210 {
1211     RenderObject* renderer = 0;
1212     if (d->m_selection.rootEditableElement())
1213         renderer = d->m_selection.rootEditableElement()->shadowAncestorNode()->renderer();
1214
1215     // If the current selection is in a textfield or textarea, notify the renderer that the selection has changed
1216     if (renderer && (renderer->isTextArea() || renderer->isTextField()))
1217         static_cast<RenderTextControl*>(renderer)->selectionChanged(userTriggered);
1218 }
1219
1220 void Frame::setDragCaret(const SelectionController& dragCaret)
1221 {
1222     d->m_page->setDragCaret(dragCaret);
1223 }
1224
1225 void Frame::invalidateSelection()
1226 {
1227     clearCaretRectIfNeeded();
1228     d->m_selection.setNeedsLayout();
1229     selectionLayoutChanged();
1230 }
1231
1232 void Frame::setCaretVisible(bool flag)
1233 {
1234     if (d->m_caretVisible == flag)
1235         return;
1236     clearCaretRectIfNeeded();
1237     if (flag)
1238         setFocusNodeIfNeeded();
1239     d->m_caretVisible = flag;
1240     selectionLayoutChanged();
1241 }
1242
1243
1244 void Frame::clearCaretRectIfNeeded()
1245 {
1246     if (d->m_caretPaint) {
1247         d->m_caretPaint = false;
1248         d->m_selection.needsCaretRepaint();
1249     }        
1250 }
1251
1252 // Helper function that tells whether a particular node is an element that has an entire
1253 // Frame and FrameView, a <frame>, <iframe>, or <object>.
1254 static bool isFrameElement(const Node *n)
1255 {
1256     if (!n)
1257         return false;
1258     RenderObject *renderer = n->renderer();
1259     if (!renderer || !renderer->isWidget())
1260         return false;
1261     Widget* widget = static_cast<RenderWidget*>(renderer)->widget();
1262     return widget && widget->isFrameView();
1263 }
1264
1265 void Frame::setFocusNodeIfNeeded()
1266 {
1267     if (!document() || d->m_selection.isNone() || !d->m_isActive)
1268         return;
1269
1270     Node *startNode = d->m_selection.start().node();
1271     Node *target = startNode ? startNode->rootEditableElement() : 0;
1272     
1273     if (target) {
1274         RenderObject* renderer = target->renderer();
1275
1276         // Walk up the render tree to search for a node to focus.
1277         // Walking up the DOM tree wouldn't work for shadow trees, like those behind the engine-based text fields.
1278         while (renderer) {
1279             // We don't want to set focus on a subframe when selecting in a parent frame,
1280             // so add the !isFrameElement check here. There's probably a better way to make this
1281             // work in the long term, but this is the safest fix at this time.
1282             if (target && target->isMouseFocusable() && !isFrameElement(target)) {
1283                 document()->setFocusNode(target);
1284                 return;
1285             }
1286             renderer = renderer->parent();
1287             if (renderer)
1288                 target = renderer->element();
1289         }
1290         document()->setFocusNode(0);
1291     }
1292 }
1293
1294 void Frame::selectionLayoutChanged()
1295 {
1296     // kill any caret blink timer now running
1297     d->m_caretBlinkTimer.stop();
1298
1299     // see if a new caret blink timer needs to be started
1300     if (d->m_caretVisible && d->m_caretBlinks && 
1301         d->m_selection.isCaret() && d->m_selection.start().node()->isContentEditable()) {
1302         d->m_caretBlinkTimer.startRepeating(caretBlinkFrequency);
1303         d->m_caretPaint = true;
1304         d->m_selection.needsCaretRepaint();
1305     }
1306
1307     if (d->m_doc)
1308         d->m_doc->updateSelection();
1309 }
1310
1311 void Frame::setXPosForVerticalArrowNavigation(int x)
1312 {
1313     d->m_xPosForVerticalArrowNavigation = x;
1314 }
1315
1316 int Frame::xPosForVerticalArrowNavigation() const
1317 {
1318     return d->m_xPosForVerticalArrowNavigation;
1319 }
1320
1321 void Frame::caretBlinkTimerFired(Timer<Frame>*)
1322 {
1323     // Might be better to turn the timer off during some of these circumstances
1324     // and assert rather then letting the timer fire and do nothing here.
1325     // Could do that in selectionLayoutChanged.
1326
1327     if (!d->m_caretVisible)
1328         return;
1329     if (!d->m_caretBlinks)
1330         return;
1331     if (!d->m_selection.isCaret())
1332         return;
1333     bool caretPaint = d->m_caretPaint;
1334     if (d->m_bMousePressed && caretPaint)
1335         return;
1336     d->m_caretPaint = !caretPaint;
1337     d->m_selection.needsCaretRepaint();
1338 }
1339
1340 void Frame::paintCaret(GraphicsContext* p, const IntRect& rect) const
1341 {
1342     if (d->m_caretPaint)
1343         d->m_selection.paintCaret(p, rect);
1344 }
1345
1346 void Frame::paintDragCaret(GraphicsContext* p, const IntRect& rect) const
1347 {
1348     SelectionController& dragCaret = d->m_page->dragCaret();
1349     assert(dragCaret.selection().isCaret());
1350     if (dragCaret.selection().start().node()->document()->frame() == this)
1351         dragCaret.paintCaret(p, rect);
1352 }
1353
1354 void Frame::urlSelected(const DeprecatedString& url, const String& target)
1355 {
1356     urlSelected(ResourceRequest(completeURL(url)), target);
1357 }
1358
1359 void Frame::urlSelected(const ResourceRequest& request, const String& _target)
1360 {
1361   String target = _target;
1362   if (target.isEmpty() && d->m_doc)
1363     target = d->m_doc->baseTarget();
1364
1365   const KURL& url = request.url();
1366
1367   if (url.url().startsWith("javascript:", false)) {
1368     executeScript(0, KURL::decode_string(url.url().mid(11)), true);
1369     return;
1370   }
1371
1372   if (!url.isValid())
1373     // ### ERROR HANDLING
1374     return;
1375
1376   ResourceRequest requestCopy = request;
1377   requestCopy.frameName = target;
1378
1379   if (d->m_bHTTPRefresh)
1380     d->m_bHTTPRefresh = false;
1381
1382   if (!d->m_referrer.isEmpty())
1383     requestCopy.setReferrer(d->m_referrer);
1384
1385   urlSelected(requestCopy);
1386 }
1387
1388 bool Frame::requestFrame(Element* ownerElement, const String& urlParam, const AtomicString& frameName)
1389 {
1390     DeprecatedString _url = urlParam.deprecatedString();
1391     // Support for <frame src="javascript:string">
1392     KURL scriptURL;
1393     KURL url;
1394     if (_url.startsWith("javascript:", false)) {
1395         scriptURL = _url;
1396         url = "about:blank";
1397     } else
1398         url = completeURL(_url);
1399
1400     Frame* frame = tree()->child(frameName);
1401     if (frame) {
1402         ResourceRequest request(url);
1403         request.setReferrer(d->m_referrer);
1404         request.reload = (d->m_cachePolicy == CachePolicyReload) || (d->m_cachePolicy == CachePolicyRefresh);
1405         frame->openURLRequest(request);
1406     } else
1407         frame = loadSubframe(ownerElement, url, frameName, d->m_referrer);
1408     
1409     if (!frame)
1410         return false;
1411
1412     if (!scriptURL.isEmpty())
1413         frame->replaceContentsWithScriptResult(scriptURL);
1414
1415     return true;
1416 }
1417
1418 bool Frame::requestObject(RenderPart* renderer, const String& url, const AtomicString& frameName,
1419                           const String& mimeType, const Vector<String>& paramNames, const Vector<String>& paramValues)
1420 {
1421     KURL completedURL;
1422     if (!url.isEmpty())
1423         completedURL = completeURL(url.deprecatedString());
1424     
1425     if (url.isEmpty() && mimeType.isEmpty())
1426         return true;
1427     
1428     bool useFallback;
1429     if (shouldUsePlugin(renderer->element(), completedURL, mimeType, renderer->hasFallbackContent(), useFallback))
1430         return loadPlugin(renderer, completedURL, mimeType, paramNames, paramValues, useFallback);
1431
1432     ASSERT(renderer->node()->hasTagName(objectTag) || renderer->node()->hasTagName(embedTag));
1433     AtomicString uniqueFrameName = tree()->uniqueChildName(frameName);
1434     static_cast<HTMLPlugInElement*>(renderer->node())->setFrameName(uniqueFrameName);
1435     
1436     // FIXME: ok to always make a new one? when does the old frame get removed?
1437     return loadSubframe(static_cast<Element*>(renderer->node()), completedURL, uniqueFrameName, d->m_referrer);
1438 }
1439
1440 bool Frame::shouldUsePlugin(Node* element, const KURL& url, const String& mimeType, bool hasFallback, bool& useFallback)
1441 {
1442     useFallback = false;
1443     ObjectContentType objectType = objectContentType(url, mimeType);
1444
1445     // if an object's content can't be handled and it has no fallback, let
1446     // it be handled as a plugin to show the broken plugin icon
1447     if (objectType == ObjectContentNone && hasFallback)
1448         useFallback = true;
1449
1450     return objectType == ObjectContentNone || objectType == ObjectContentPlugin;
1451 }
1452
1453
1454 bool Frame::loadPlugin(RenderPart *renderer, const KURL& url, const String& mimeType, 
1455                        const Vector<String>& paramNames, const Vector<String>& paramValues, bool useFallback)
1456 {
1457     if (useFallback) {
1458         checkEmitLoadEvent();
1459         return false;
1460     }
1461
1462     Element *pluginElement;
1463     if (renderer && renderer->node() && renderer->node()->isElementNode())
1464         pluginElement = static_cast<Element*>(renderer->node());
1465     else
1466         pluginElement = 0;
1467         
1468     Plugin* plugin = createPlugin(pluginElement, url, paramNames, paramValues, mimeType);
1469     if (!plugin) {
1470         checkEmitLoadEvent();
1471         return false;
1472     }
1473     d->m_plugins.append(plugin);
1474     
1475     if (renderer && plugin->view())
1476         renderer->setWidget(plugin->view());
1477     
1478     checkEmitLoadEvent();
1479     
1480     return true;
1481 }
1482
1483 Frame* Frame::loadSubframe(Element* ownerElement, const KURL& url, const String& name, const String& referrer)
1484 {
1485     Frame* frame = createFrame(url, name, ownerElement, referrer);
1486     if (!frame)  {
1487         checkEmitLoadEvent();
1488         return 0;
1489     }
1490     
1491     frame->childBegin();
1492     
1493     if (ownerElement->renderer() && frame->view())
1494         static_cast<RenderWidget*>(ownerElement->renderer())->setWidget(frame->view());
1495     
1496     checkEmitLoadEvent();
1497     
1498     // In these cases, the synchronous load would have finished
1499     // before we could connect the signals, so make sure to send the 
1500     // completed() signal for the child by hand
1501     // FIXME: In this case the Frame will have finished loading before 
1502     // it's being added to the child list. It would be a good idea to
1503     // create the child first, then invoke the loader separately.
1504     if (url.isEmpty() || url == "about:blank") {
1505         frame->completed(false);
1506         frame->checkCompleted();
1507     }
1508
1509     return frame;
1510 }
1511
1512 void Frame::clearRecordedFormValues()
1513 {
1514     d->m_formAboutToBeSubmitted = 0;
1515     d->m_formValuesAboutToBeSubmitted.clear();
1516 }
1517
1518 void Frame::recordFormValue(const String& name, const String& value, PassRefPtr<HTMLFormElement> element)
1519 {
1520     d->m_formAboutToBeSubmitted = element;
1521     d->m_formValuesAboutToBeSubmitted.set(name, value);
1522 }
1523
1524 void Frame::submitFormAgain()
1525 {
1526     FramePrivate::SubmitForm* form = d->m_submitForm;
1527     d->m_submitForm = 0;
1528     if (d->m_doc && !d->m_doc->parsing() && form)
1529         submitForm(form->submitAction, form->submitUrl, form->submitFormData,
1530             form->target, form->submitContentType, form->submitBoundary);
1531     delete form;
1532 }
1533
1534 void Frame::submitForm(const char *action, const String& url, const FormData& formData, const String& _target, const String& contentType, const String& boundary)
1535 {
1536   KURL u = completeURL(url.deprecatedString());
1537
1538   if (!u.isValid())
1539     // ### ERROR HANDLING!
1540     return;
1541
1542   DeprecatedString urlstring = u.url();
1543   if (urlstring.startsWith("javascript:", false)) {
1544     urlstring = KURL::decode_string(urlstring);
1545     d->m_executingJavaScriptFormAction = true;
1546     executeScript(0, urlstring.mid(11));
1547     d->m_executingJavaScriptFormAction = false;
1548     return;
1549   }
1550
1551   ResourceRequest request;
1552
1553   if (!d->m_referrer.isEmpty())
1554      request.setReferrer(d->m_referrer);
1555
1556   request.frameName = _target.isEmpty() ? d->m_doc->baseTarget() : _target ;
1557
1558   // Handle mailto: forms
1559   if (u.protocol() == "mailto") {
1560       // 1)  Check for attach= and strip it
1561       DeprecatedString q = u.query().mid(1);
1562       DeprecatedStringList nvps = DeprecatedStringList::split("&", q);
1563       bool triedToAttach = false;
1564
1565       for (DeprecatedStringList::Iterator nvp = nvps.begin(); nvp != nvps.end(); ++nvp) {
1566          DeprecatedStringList pair = DeprecatedStringList::split("=", *nvp);
1567          if (pair.count() >= 2) {
1568             if (pair.first().lower() == "attach") {
1569                nvp = nvps.remove(nvp);
1570                triedToAttach = true;
1571             }
1572          }
1573       }
1574
1575
1576       // 2)  Append body=
1577       DeprecatedString bodyEnc;
1578       if (contentType.lower() == "multipart/form-data")
1579          // FIXME: is this correct?  I suspect not
1580          bodyEnc = KURL::encode_string(formData.flattenToString());
1581       else if (contentType.lower() == "text/plain") {
1582          // Convention seems to be to decode, and s/&/\n/
1583          DeprecatedString tmpbody = formData.flattenToString();
1584          tmpbody.replace('&', '\n');
1585          tmpbody.replace('+', ' ');
1586          tmpbody = KURL::decode_string(tmpbody);  // Decode the rest of it
1587          bodyEnc = KURL::encode_string(tmpbody);  // Recode for the URL
1588       } else
1589          bodyEnc = KURL::encode_string(formData.flattenToString());
1590
1591       nvps.append(String::sprintf("body=%s", bodyEnc.latin1()).deprecatedString());
1592       q = nvps.join("&");
1593       u.setQuery(q);
1594   } 
1595
1596   if (strcmp(action, "get") == 0) {
1597     if (u.protocol() != "mailto")
1598        u.setQuery(formData.flattenToString());
1599     request.setDoPost(false);
1600   } else {
1601     request.postData = formData;
1602     request.setDoPost(true);
1603
1604     // construct some user headers if necessary
1605     if (contentType.isNull() || contentType == "application/x-www-form-urlencoded")
1606       request.setContentType("Content-Type: application/x-www-form-urlencoded");
1607     else // contentType must be "multipart/form-data"
1608       request.setContentType("Content-Type: " + contentType + "; boundary=" + boundary);
1609   }
1610
1611   if (d->m_doc->parsing() || d->m_runningScripts > 0) {
1612     if (d->m_submitForm)
1613         return;
1614     d->m_submitForm = new FramePrivate::SubmitForm;
1615     d->m_submitForm->submitAction = action;
1616     d->m_submitForm->submitUrl = url;
1617     d->m_submitForm->submitFormData = formData;
1618     d->m_submitForm->target = _target;
1619     d->m_submitForm->submitContentType = contentType;
1620     d->m_submitForm->submitBoundary = boundary;
1621   } else {
1622       request.setURL(u);
1623       submitForm(request);
1624   }
1625 }
1626
1627 void Frame::parentCompleted()
1628 {
1629     if (d->m_scheduledRedirection != noRedirectionScheduled && !d->m_redirectionTimer.isActive())
1630         startRedirectionTimer();
1631 }
1632
1633 void Frame::childCompleted(bool complete)
1634 {
1635     if (complete && !tree()->parent())
1636         d->m_bPendingChildRedirection = true;
1637     checkCompleted();
1638 }
1639
1640 int Frame::zoomFactor() const
1641 {
1642   return d->m_zoomFactor;
1643 }
1644
1645 void Frame::setZoomFactor(int percent)
1646 {  
1647   if (d->m_zoomFactor == percent)
1648       return;
1649
1650   d->m_zoomFactor = percent;
1651
1652   if (d->m_doc)
1653       d->m_doc->recalcStyle(Node::Force);
1654
1655   for (Frame* child = tree()->firstChild(); child; child = child->tree()->nextSibling())
1656       child->setZoomFactor(d->m_zoomFactor);
1657
1658   if (d->m_doc && d->m_doc->renderer() && d->m_doc->renderer()->needsLayout())
1659       view()->layout();
1660 }
1661
1662 void Frame::setJSStatusBarText(const String& text)
1663 {
1664     d->m_kjsStatusBarText = text;
1665     setStatusBarText(d->m_kjsStatusBarText);
1666 }
1667
1668 void Frame::setJSDefaultStatusBarText(const String& text)
1669 {
1670     d->m_kjsDefaultStatusBarText = text;
1671     setStatusBarText(d->m_kjsDefaultStatusBarText);
1672 }
1673
1674 String Frame::jsStatusBarText() const
1675 {
1676     return d->m_kjsStatusBarText;
1677 }
1678
1679 String Frame::jsDefaultStatusBarText() const
1680 {
1681    return d->m_kjsDefaultStatusBarText;
1682 }
1683
1684 DeprecatedString Frame::referrer() const
1685 {
1686     return d->m_referrer;
1687 }
1688
1689 String Frame::lastModified() const
1690 {
1691     return d->m_lastModified;
1692 }
1693
1694 void Frame::reparseConfiguration()
1695 {
1696     setAutoloadImages(d->m_settings->autoLoadImages());
1697         
1698     d->m_bJScriptEnabled = d->m_settings->isJavaScriptEnabled();
1699     d->m_bJavaEnabled = d->m_settings->isJavaEnabled();
1700     d->m_bPluginsEnabled = d->m_settings->isPluginsEnabled();
1701
1702     const KURL& userStyleSheetLocation = d->m_settings->userStyleSheetLocation();
1703     if (!userStyleSheetLocation.isEmpty())
1704         setUserStyleSheetLocation(userStyleSheetLocation);
1705     else
1706         setUserStyleSheet(String());
1707
1708     // FIXME: It's not entirely clear why the following is needed.
1709     // The document automatically does this as required when you set the style sheet.
1710     // But we had problems when this code was removed. Details are in
1711     // <http://bugzilla.opendarwin.org/show_bug.cgi?id=8079>.
1712     if (d->m_doc)
1713         d->m_doc->updateStyleSelector();
1714 }
1715
1716 bool Frame::shouldDragAutoNode(Node *node, const IntPoint& point) const
1717 {
1718     // No KDE impl yet
1719     return false;
1720 }
1721
1722 bool Frame::isPointInsideSelection(const IntPoint& point)
1723 {
1724     // Treat a collapsed selection like no selection.
1725     if (!d->m_selection.isRange())
1726         return false;
1727     if (!document()->renderer()) 
1728         return false;
1729     
1730     RenderObject::NodeInfo nodeInfo(true, true);
1731     document()->renderer()->layer()->hitTest(nodeInfo, point);
1732     Node *innerNode = nodeInfo.innerNode();
1733     if (!innerNode || !innerNode->renderer())
1734         return false;
1735     
1736     Position pos(innerNode->renderer()->positionForPoint(point).deepEquivalent());
1737     if (pos.isNull())
1738         return false;
1739
1740     Node *n = d->m_selection.start().node();
1741     while (n) {
1742         if (n == pos.node()) {
1743             if ((n == d->m_selection.start().node() && pos.offset() < d->m_selection.start().offset()) ||
1744                 (n == d->m_selection.end().node() && pos.offset() > d->m_selection.end().offset())) {
1745                 return false;
1746             }
1747             return true;
1748         }
1749         if (n == d->m_selection.end().node())
1750             break;
1751         n = n->traverseNextNode();
1752     }
1753
1754    return false;
1755 }
1756
1757 void Frame::selectClosestWordFromMouseEvent(const PlatformMouseEvent& mouse, Node *innerNode)
1758 {
1759     SelectionController selection;
1760
1761     if (innerNode && innerNode->renderer() && mouseDownMayStartSelect() && innerNode->renderer()->shouldSelect()) {
1762         IntPoint vPoint = view()->viewportToContents(mouse.pos());
1763         VisiblePosition pos(innerNode->renderer()->positionForPoint(vPoint));
1764         if (pos.isNotNull()) {
1765             selection.moveTo(pos);
1766             selection.expandUsingGranularity(WordGranularity);
1767         }
1768     }
1769     
1770     if (selection.isRange()) {
1771         d->m_selectionGranularity = WordGranularity;
1772         d->m_beganSelectingText = true;
1773     }
1774     
1775     if (shouldChangeSelection(selection))
1776         setSelection(selection);
1777 }
1778
1779 void Frame::handleMousePressEventDoubleClick(const MouseEventWithHitTestResults& event)
1780 {
1781     if (event.event().button() == LeftButton) {
1782         if (selection().isRange())
1783             // A double-click when range is already selected
1784             // should not change the selection.  So, do not call
1785             // selectClosestWordFromMouseEvent, but do set
1786             // m_beganSelectingText to prevent handleMouseReleaseEvent
1787             // from setting caret selection.
1788             d->m_beganSelectingText = true;
1789         else
1790             selectClosestWordFromMouseEvent(event.event(), event.targetNode());
1791     }
1792 }
1793
1794 void Frame::handleMousePressEventTripleClick(const MouseEventWithHitTestResults& event)
1795 {
1796     Node *innerNode = event.targetNode();
1797     
1798     if (event.event().button() == LeftButton && innerNode && innerNode->renderer() &&
1799         mouseDownMayStartSelect() && innerNode->renderer()->shouldSelect()) {
1800         SelectionController selection;
1801         IntPoint vPoint = view()->viewportToContents(event.event().pos());
1802         VisiblePosition pos(innerNode->renderer()->positionForPoint(vPoint));
1803         if (pos.isNotNull()) {
1804             selection.moveTo(pos);
1805             selection.expandUsingGranularity(ParagraphGranularity);
1806         }
1807         if (selection.isRange()) {
1808             d->m_selectionGranularity = ParagraphGranularity;
1809             d->m_beganSelectingText = true;
1810         }
1811         
1812         if (shouldChangeSelection(selection))
1813             setSelection(selection);
1814     }
1815 }
1816
1817 void Frame::handleMousePressEventSingleClick(const MouseEventWithHitTestResults& event)
1818 {
1819     Node *innerNode = event.targetNode();
1820     
1821     if (event.event().button() == LeftButton) {
1822         if (innerNode && innerNode->renderer() &&
1823             mouseDownMayStartSelect() && innerNode->renderer()->shouldSelect()) {
1824             SelectionController sel;
1825             
1826             // Extend the selection if the Shift key is down, unless the click is in a link.
1827             bool extendSelection = event.event().shiftKey() && !event.isOverLink();
1828
1829             // Don't restart the selection when the mouse is pressed on an
1830             // existing selection so we can allow for text dragging.
1831             IntPoint vPoint = view()->viewportToContents(event.event().pos());
1832             if (!extendSelection && isPointInsideSelection(vPoint))
1833                 return;
1834
1835             VisiblePosition visiblePos(innerNode->renderer()->positionForPoint(vPoint));
1836             if (visiblePos.isNull())
1837                 visiblePos = VisiblePosition(innerNode, innerNode->caretMinOffset(), DOWNSTREAM);
1838             Position pos = visiblePos.deepEquivalent();
1839             
1840             sel = selection();
1841             if (extendSelection && sel.isCaretOrRange()) {
1842                 sel.clearModifyBias();
1843                 
1844                 // See <rdar://problem/3668157> REGRESSION (Mail): shift-click deselects when selection 
1845                 // was created right-to-left
1846                 Position start = sel.start();
1847                 short before = Range::compareBoundaryPoints(pos.node(), pos.offset(), start.node(), start.offset());
1848                 if (before <= 0)
1849                     sel.setBaseAndExtent(pos.node(), pos.offset(), sel.end().node(), sel.end().offset());
1850                 else
1851                     sel.setBaseAndExtent(start.node(), start.offset(), pos.node(), pos.offset());
1852
1853                 if (d->m_selectionGranularity != CharacterGranularity)
1854                     sel.expandUsingGranularity(d->m_selectionGranularity);
1855                 d->m_beganSelectingText = true;
1856             } else {
1857                 sel = SelectionController(visiblePos);
1858                 d->m_selectionGranularity = CharacterGranularity;
1859             }
1860             
1861             if (shouldChangeSelection(sel))
1862                 setSelection(sel);
1863         }
1864     }
1865 }
1866
1867 void Frame::handleMousePressEvent(const MouseEventWithHitTestResults& event)
1868 {
1869     Node *innerNode = event.targetNode();
1870
1871     d->m_mousePressNode = innerNode;
1872     d->m_dragStartPos = event.event().pos();
1873
1874     if (event.event().button() == LeftButton || event.event().button() == MiddleButton) {
1875         d->m_bMousePressed = true;
1876         d->m_beganSelectingText = false;
1877
1878         if (event.event().clickCount() == 2) {
1879             handleMousePressEventDoubleClick(event);
1880             return;
1881         }
1882         if (event.event().clickCount() >= 3) {
1883             handleMousePressEventTripleClick(event);
1884             return;
1885         }
1886         handleMousePressEventSingleClick(event);
1887     }
1888 }
1889
1890 void Frame::handleMouseMoveEvent(const MouseEventWithHitTestResults& event)
1891 {
1892     // Mouse not pressed. Do nothing.
1893     if (!d->m_bMousePressed)
1894         return;
1895
1896     Node *innerNode = event.targetNode();
1897
1898     if (event.event().button() != 0 || !innerNode || !innerNode->renderer() || !mouseDownMayStartSelect() || !innerNode->renderer()->shouldSelect())
1899         return;
1900
1901     // handle making selection
1902     IntPoint vPoint = view()->viewportToContents(event.event().pos());
1903     VisiblePosition pos(innerNode->renderer()->positionForPoint(vPoint));
1904
1905     // Don't modify the selection if we're not on a node.
1906     if (pos.isNull())
1907         return;
1908
1909     // Restart the selection if this is the first mouse move. This work is usually
1910     // done in handleMousePressEvent, but not if the mouse press was on an existing selection.
1911     SelectionController sel = selection();
1912     sel.clearModifyBias();
1913     
1914     if (!d->m_beganSelectingText) {
1915         d->m_beganSelectingText = true;
1916         sel.moveTo(pos);
1917     }
1918
1919     sel.setExtent(pos);
1920     if (d->m_selectionGranularity != CharacterGranularity)
1921         sel.expandUsingGranularity(d->m_selectionGranularity);
1922
1923     if (shouldChangeSelection(sel))
1924         setSelection(sel);
1925 }
1926
1927 void Frame::handleMouseReleaseEvent(const MouseEventWithHitTestResults& event)
1928 {
1929     stopAutoscrollTimer();
1930     
1931     // Used to prevent mouseMoveEvent from initiating a drag before
1932     // the mouse is pressed again.
1933     d->m_bMousePressed = false;
1934   
1935     // Clear the selection if the mouse didn't move after the last mouse press.
1936     // We do this so when clicking on the selection, the selection goes away.
1937     // However, if we are editing, place the caret.
1938     if (mouseDownMayStartSelect() && !d->m_beganSelectingText
1939             && d->m_dragStartPos == event.event().pos()
1940             && d->m_selection.isRange()) {
1941         SelectionController selection;
1942         Node *node = event.targetNode();
1943         if (node && node->isContentEditable() && node->renderer()) {
1944             IntPoint vPoint = view()->viewportToContents(event.event().pos());
1945             VisiblePosition pos = node->renderer()->positionForPoint(vPoint);
1946             selection.moveTo(pos);
1947         }
1948         if (shouldChangeSelection(selection))
1949             setSelection(selection);
1950     }
1951
1952     notifyRendererOfSelectionChange(true);
1953
1954     selectFrameElementInParentIfFullySelected();
1955 }
1956
1957 void Frame::selectAll()
1958 {
1959     if (!d->m_doc)
1960         return;
1961     
1962     Node *startNode = d->m_selection.start().node();
1963     Node *root = startNode && startNode->isContentEditable() ? startNode->rootEditableElement() : d->m_doc->documentElement();
1964     
1965     selectContentsOfNode(root);
1966     selectFrameElementInParentIfFullySelected();
1967 }
1968
1969 bool Frame::selectContentsOfNode(Node* node)
1970 {
1971     SelectionController sel = SelectionController(Selection::selectionFromContentsOfNode(node));    
1972     if (shouldChangeSelection(sel)) {
1973         setSelection(sel);
1974         return true;
1975     }
1976     return false;
1977 }
1978
1979 bool Frame::shouldChangeSelection(const SelectionController& newselection) const
1980 {
1981     return shouldChangeSelection(d->m_selection, newselection, newselection.affinity(), false);
1982 }
1983
1984 bool Frame::shouldDeleteSelection(const SelectionController& newselection) const
1985 {
1986     return true;
1987 }
1988
1989 bool Frame::shouldBeginEditing(const Range *range) const
1990 {
1991     return true;
1992 }
1993
1994 bool Frame::shouldEndEditing(const Range *range) const
1995 {
1996     return true;
1997 }
1998
1999 bool Frame::isContentEditable() const 
2000 {
2001     if (!d->m_doc)
2002         return false;
2003     return d->m_doc->inDesignMode();
2004 }
2005
2006 void Frame::textFieldDidBeginEditing(Element* input)
2007 {
2008 }
2009
2010 void Frame::textFieldDidEndEditing(Element* input)
2011 {
2012 }
2013
2014 void Frame::textDidChangeInTextField(Element* input)
2015 {
2016 }
2017
2018 bool Frame::doTextFieldCommandFromEvent(Element* input, const PlatformKeyboardEvent* evt)
2019 {
2020     return false;
2021 }
2022
2023 void Frame::textWillBeDeletedInTextField(Element* input)
2024 {
2025 }
2026
2027 void Frame::textDidChangeInTextArea(Element* input)
2028 {
2029 }
2030
2031 EditCommandPtr Frame::lastEditCommand()
2032 {
2033     return d->m_lastEditCommand;
2034 }
2035
2036 void dispatchEditableContentChangedEvent(Node* root)
2037 {
2038     if (!root)
2039         return;
2040         
2041     ExceptionCode ec = 0;
2042     EventTargetNodeCast(root)->dispatchEvent(new Event(khtmlEditableContentChangedEvent, false, false), ec, true);
2043 }
2044
2045 void Frame::appliedEditing(EditCommandPtr& cmd)
2046 {
2047     SelectionController sel(cmd.endingSelection());
2048     if (shouldChangeSelection(sel))
2049         setSelection(sel, false);
2050     
2051     dispatchEditableContentChangedEvent(!selection().isNone() ? selection().start().node()->rootEditableElement() : 0);
2052
2053     // Now set the typing style from the command. Clear it when done.
2054     // This helps make the case work where you completely delete a piece
2055     // of styled text and then type a character immediately after.
2056     // That new character needs to take on the style of the just-deleted text.
2057     // FIXME: Improve typing style.
2058     // See this bug: <rdar://problem/3769899> Implementation of typing style needs improvement
2059     if (cmd.typingStyle()) {
2060         setTypingStyle(cmd.typingStyle());
2061         cmd.setTypingStyle(0);
2062     }
2063
2064     // Command will be equal to last edit command only in the case of typing
2065     if (d->m_lastEditCommand == cmd) {
2066         assert(cmd.isTypingCommand());
2067     }
2068     else {
2069         // Only register a new undo command if the command passed in is
2070         // different from the last command
2071         registerCommandForUndo(cmd);
2072         d->m_lastEditCommand = cmd;
2073     }
2074     respondToChangedContents();
2075 }
2076
2077 void Frame::unappliedEditing(EditCommandPtr& cmd)
2078 {
2079     SelectionController sel(cmd.startingSelection());
2080     if (shouldChangeSelection(sel))
2081         setSelection(sel, true);
2082     
2083     dispatchEditableContentChangedEvent(!selection().isNone() ? selection().start().node()->rootEditableElement() : 0);
2084         
2085     registerCommandForRedo(cmd);
2086     respondToChangedContents();
2087     d->m_lastEditCommand = EditCommandPtr::emptyCommand();
2088 }
2089
2090 void Frame::reappliedEditing(EditCommandPtr& cmd)
2091 {
2092     SelectionController sel(cmd.endingSelection());
2093     if (shouldChangeSelection(sel))
2094         setSelection(sel, true);
2095     
2096     dispatchEditableContentChangedEvent(!selection().isNone() ? selection().start().node()->rootEditableElement() : 0);
2097         
2098     registerCommandForUndo(cmd);
2099     respondToChangedContents();
2100     d->m_lastEditCommand = EditCommandPtr::emptyCommand();
2101 }
2102
2103 CSSMutableStyleDeclaration *Frame::typingStyle() const
2104 {
2105     return d->m_typingStyle.get();
2106 }
2107
2108 void Frame::setTypingStyle(CSSMutableStyleDeclaration *style)
2109 {
2110     d->m_typingStyle = style;
2111 }
2112
2113 void Frame::clearTypingStyle()
2114 {
2115     d->m_typingStyle = 0;
2116 }
2117
2118 JSValue* Frame::executeScript(const String& filename, int baseLine, Node* n, const DeprecatedString& script)
2119 {
2120   // FIXME: This is missing stuff that the other executeScript has.
2121   // --> d->m_runningScripts and submitFormAgain.
2122   // Why is that OK?
2123   KJSProxy *proxy = jScript();
2124   if (!proxy)
2125     return 0;
2126   JSValue* ret = proxy->evaluate(filename, baseLine, script, n);
2127   Document::updateDocumentsRendering();
2128   return ret;
2129 }
2130
2131 Frame *Frame::opener()
2132 {
2133     return d->m_opener;
2134 }
2135
2136 void Frame::setOpener(Frame* opener)
2137 {
2138     if (d->m_opener)
2139         d->m_opener->d->m_openedFrames.remove(this);
2140     if (opener)
2141         opener->d->m_openedFrames.add(this);
2142     d->m_opener = opener;
2143 }
2144
2145 bool Frame::openedByJS()
2146 {
2147     return d->m_openedByJS;
2148 }
2149
2150 void Frame::setOpenedByJS(bool _openedByJS)
2151 {
2152     d->m_openedByJS = _openedByJS;
2153 }
2154
2155 bool Frame::tabsToLinks() const
2156 {
2157     return true;
2158 }
2159
2160 bool Frame::tabsToAllControls() const
2161 {
2162     return true;
2163 }
2164
2165 void Frame::copyToPasteboard()
2166 {
2167     issueCopyCommand();
2168 }
2169
2170 void Frame::cutToPasteboard()
2171 {
2172     issueCutCommand();
2173 }
2174
2175 void Frame::pasteFromPasteboard()
2176 {
2177     issuePasteCommand();
2178 }
2179
2180 void Frame::pasteAndMatchStyle()
2181 {
2182     issuePasteAndMatchStyleCommand();
2183 }
2184
2185 void Frame::transpose()
2186 {
2187     issueTransposeCommand();
2188 }
2189
2190 void Frame::redo()
2191 {
2192     issueRedoCommand();
2193 }
2194
2195 void Frame::undo()
2196 {
2197     issueUndoCommand();
2198 }
2199
2200
2201 void Frame::computeAndSetTypingStyle(CSSStyleDeclaration *style, EditAction editingAction)
2202 {
2203     if (!style || style->length() == 0) {
2204         clearTypingStyle();
2205         return;
2206     }
2207
2208     // Calculate the current typing style.
2209     RefPtr<CSSMutableStyleDeclaration> mutableStyle = style->makeMutable();
2210     if (typingStyle()) {
2211         typingStyle()->merge(mutableStyle.get());
2212         mutableStyle = typingStyle();
2213     }
2214
2215     Node *node = VisiblePosition(selection().start(), selection().affinity()).deepEquivalent().node();
2216     CSSComputedStyleDeclaration computedStyle(node);
2217     computedStyle.diff(mutableStyle.get());
2218     
2219     // Handle block styles, substracting these from the typing style.
2220     RefPtr<CSSMutableStyleDeclaration> blockStyle = mutableStyle->copyBlockProperties();
2221     blockStyle->diff(mutableStyle.get());
2222     if (document() && blockStyle->length() > 0) {
2223         EditCommandPtr cmd(new ApplyStyleCommand(document(), blockStyle.get(), editingAction));
2224         cmd.apply();
2225     }
2226     
2227     // Set the remaining style as the typing style.
2228     d->m_typingStyle = mutableStyle.release();
2229 }
2230
2231 void Frame::applyStyle(CSSStyleDeclaration *style, EditAction editingAction)
2232 {
2233     switch (selection().state()) {
2234         case Selection::NONE:
2235             // do nothing
2236             break;
2237         case Selection::CARET: {
2238             computeAndSetTypingStyle(style, editingAction);
2239             break;
2240         }
2241         case Selection::RANGE:
2242             if (document() && style) {
2243                 EditCommandPtr cmd(new ApplyStyleCommand(document(), style, editingAction));
2244                 cmd.apply();
2245             }
2246             break;
2247     }
2248 }
2249
2250 void Frame::applyParagraphStyle(CSSStyleDeclaration *style, EditAction editingAction)
2251 {
2252     switch (selection().state()) {
2253         case Selection::NONE:
2254             // do nothing
2255             break;
2256         case Selection::CARET:
2257         case Selection::RANGE:
2258             if (document() && style) {
2259                 EditCommandPtr cmd(new ApplyStyleCommand(document(), style, editingAction, ApplyStyleCommand::ForceBlockProperties));
2260                 cmd.apply();
2261             }
2262             break;
2263     }
2264 }
2265
2266 static void updateState(CSSMutableStyleDeclaration *desiredStyle, CSSComputedStyleDeclaration *computedStyle, bool& atStart, Frame::TriState& state)
2267 {
2268     DeprecatedValueListConstIterator<CSSProperty> end;
2269     for (DeprecatedValueListConstIterator<CSSProperty> it = desiredStyle->valuesIterator(); it != end; ++it) {
2270         int propertyID = (*it).id();
2271         String desiredProperty = desiredStyle->getPropertyValue(propertyID);
2272         String computedProperty = computedStyle->getPropertyValue(propertyID);
2273         Frame::TriState propertyState = equalIgnoringCase(desiredProperty, computedProperty)
2274             ? Frame::trueTriState : Frame::falseTriState;
2275         if (atStart) {
2276             state = propertyState;
2277             atStart = false;
2278         } else if (state != propertyState) {
2279             state = Frame::mixedTriState;
2280             break;
2281         }
2282     }
2283 }
2284
2285 Frame::TriState Frame::selectionListState() const
2286 {
2287     TriState state = falseTriState;
2288
2289     if (!d->m_selection.isRange()) {
2290         Node* selectionNode = d->m_selection.selection().start().node();
2291         if (enclosingList(selectionNode))
2292             return trueTriState;
2293     } else {
2294         //FIXME: Support ranges
2295     }
2296
2297     return state;
2298 }
2299
2300 Frame::TriState Frame::selectionHasStyle(CSSStyleDeclaration *style) const
2301 {
2302     bool atStart = true;
2303     TriState state = falseTriState;
2304
2305     RefPtr<CSSMutableStyleDeclaration> mutableStyle = style->makeMutable();
2306
2307     if (!d->m_selection.isRange()) {
2308         Node* nodeToRemove;
2309         RefPtr<CSSComputedStyleDeclaration> selectionStyle = selectionComputedStyle(nodeToRemove);
2310         if (!selectionStyle)
2311             return falseTriState;
2312         updateState(mutableStyle.get(), selectionStyle.get(), atStart, state);
2313         if (nodeToRemove) {
2314             ExceptionCode ec = 0;
2315             nodeToRemove->remove(ec);
2316             assert(ec == 0);
2317         }
2318     } else {
2319         for (Node* node = d->m_selection.start().node(); node; node = node->traverseNextNode()) {
2320             RefPtr<CSSComputedStyleDeclaration> computedStyle = new CSSComputedStyleDeclaration(node);
2321             if (computedStyle)
2322                 updateState(mutableStyle.get(), computedStyle.get(), atStart, state);
2323             if (state == mixedTriState)
2324                 break;
2325             if (node == d->m_selection.end().node())
2326                 break;
2327         }
2328     }
2329
2330     return state;
2331 }
2332
2333 bool Frame::selectionStartHasStyle(CSSStyleDeclaration *style) const
2334 {
2335     Node* nodeToRemove;
2336     RefPtr<CSSStyleDeclaration> selectionStyle = selectionComputedStyle(nodeToRemove);
2337     if (!selectionStyle)
2338         return false;
2339
2340     RefPtr<CSSMutableStyleDeclaration> mutableStyle = style->makeMutable();
2341
2342     bool match = true;
2343     DeprecatedValueListConstIterator<CSSProperty> end;
2344     for (DeprecatedValueListConstIterator<CSSProperty> it = mutableStyle->valuesIterator(); it != end; ++it) {
2345         int propertyID = (*it).id();
2346         if (!equalIgnoringCase(mutableStyle->getPropertyValue(propertyID), selectionStyle->getPropertyValue(propertyID))) {
2347             match = false;
2348             break;
2349         }
2350     }
2351
2352     if (nodeToRemove) {
2353         ExceptionCode ec = 0;
2354         nodeToRemove->remove(ec);
2355         assert(ec == 0);
2356     }
2357
2358     return match;
2359 }
2360
2361 String Frame::selectionStartStylePropertyValue(int stylePropertyID) const
2362 {
2363     Node *nodeToRemove;
2364     RefPtr<CSSStyleDeclaration> selectionStyle = selectionComputedStyle(nodeToRemove);
2365     if (!selectionStyle)
2366         return String();
2367
2368     String value = selectionStyle->getPropertyValue(stylePropertyID);
2369
2370     if (nodeToRemove) {
2371         ExceptionCode ec = 0;
2372         nodeToRemove->remove(ec);
2373         assert(ec == 0);
2374     }
2375
2376     return value;
2377 }
2378
2379 CSSComputedStyleDeclaration *Frame::selectionComputedStyle(Node *&nodeToRemove) const
2380 {
2381     nodeToRemove = 0;
2382
2383     if (!document())
2384         return 0;
2385
2386     if (d->m_selection.isNone())
2387         return 0;
2388
2389     RefPtr<Range> range(d->m_selection.toRange());
2390     Position pos = range->editingStartPosition();
2391
2392     Element *elem = pos.element();
2393     if (!elem)
2394         return 0;
2395     
2396     RefPtr<Element> styleElement = elem;
2397     ExceptionCode ec = 0;
2398
2399     if (d->m_typingStyle) {
2400         styleElement = document()->createElementNS(xhtmlNamespaceURI, "span", ec);
2401         assert(ec == 0);
2402
2403         styleElement->setAttribute(styleAttr, d->m_typingStyle->cssText().impl(), ec);
2404         assert(ec == 0);
2405         
2406         styleElement->appendChild(document()->createEditingTextNode(""), ec);
2407         assert(ec == 0);
2408
2409         if (elem->renderer() && elem->renderer()->canHaveChildren()) {
2410             elem->appendChild(styleElement, ec);
2411         } else {
2412             Node *parent = elem->parent();
2413             Node *next = elem->nextSibling();
2414
2415             if (next) {
2416                 parent->insertBefore(styleElement, next, ec);
2417             } else {
2418                 parent->appendChild(styleElement, ec);
2419             }
2420         }
2421         assert(ec == 0);
2422
2423         nodeToRemove = styleElement.get();
2424     }
2425
2426     return new CSSComputedStyleDeclaration(styleElement);
2427 }
2428
2429 void Frame::applyEditingStyleToBodyElement() const
2430 {
2431     if (!d->m_doc)
2432         return;
2433         
2434     RefPtr<NodeList> list = d->m_doc->getElementsByTagName("body");
2435     unsigned len = list->length();
2436     for (unsigned i = 0; i < len; i++) {
2437         applyEditingStyleToElement(static_cast<Element*>(list->item(i)));    
2438     }
2439 }
2440
2441 void Frame::removeEditingStyleFromBodyElement() const
2442 {
2443     if (!d->m_doc)
2444         return;
2445         
2446     RefPtr<NodeList> list = d->m_doc->getElementsByTagName("body");
2447     unsigned len = list->length();
2448     for (unsigned i = 0; i < len; i++) {
2449         removeEditingStyleFromElement(static_cast<Element*>(list->item(i)));    
2450     }
2451 }
2452
2453 void Frame::applyEditingStyleToElement(Element* element) const
2454 {
2455     if (!element)
2456         return;
2457
2458     CSSStyleDeclaration* style = element->style();
2459     ASSERT(style);
2460
2461     ExceptionCode ec = 0;
2462     style->setProperty(CSS_PROP_WORD_WRAP, "break-word", false, ec);
2463     ASSERT(ec == 0);
2464     style->setProperty(CSS_PROP__WEBKIT_NBSP_MODE, "space", false, ec);
2465     ASSERT(ec == 0);
2466     style->setProperty(CSS_PROP__WEBKIT_LINE_BREAK, "after-white-space", false, ec);
2467     ASSERT(ec == 0);
2468 }
2469
2470 void Frame::removeEditingStyleFromElement(Element*) const
2471 {
2472 }
2473
2474 bool Frame::isCharacterSmartReplaceExempt(const DeprecatedChar&, bool)
2475 {
2476     // no smart replace
2477     return true;
2478 }
2479
2480 #ifndef NDEBUG
2481 static HashSet<Frame*> lifeSupportSet;
2482 #endif
2483
2484 void Frame::endAllLifeSupport()
2485 {
2486 #ifndef NDEBUG
2487     HashSet<Frame*> lifeSupportCopy = lifeSupportSet;
2488     HashSet<Frame*>::iterator end = lifeSupportCopy.end();
2489     for (HashSet<Frame*>::iterator it = lifeSupportCopy.begin(); it != end; ++it)
2490         (*it)->endLifeSupport();
2491 #endif
2492 }
2493
2494 void Frame::keepAlive()
2495 {
2496     if (d->m_lifeSupportTimer.isActive())
2497         return;
2498     ref();
2499 #ifndef NDEBUG
2500     lifeSupportSet.add(this);
2501 #endif
2502     d->m_lifeSupportTimer.startOneShot(0);
2503 }
2504
2505 void Frame::endLifeSupport()
2506 {
2507     if (!d->m_lifeSupportTimer.isActive())
2508         return;
2509     d->m_lifeSupportTimer.stop();
2510 #ifndef NDEBUG
2511     lifeSupportSet.remove(this);
2512 #endif
2513     deref();
2514 }
2515
2516 void Frame::lifeSupportTimerFired(Timer<Frame>*)
2517 {
2518 #ifndef NDEBUG
2519     lifeSupportSet.remove(this);
2520 #endif
2521     deref();
2522 }
2523
2524 // Workaround for the fact that it's hard to delete a frame.
2525 // Call this after doing user-triggered selections to make it easy to delete the frame you entirely selected.
2526 // Can't do this implicitly as part of every setSelection call because in some contexts it might not be good
2527 // for the focus to move to another frame. So instead we call it from places where we are selecting with the
2528 // mouse or the keyboard after setting the selection.
2529 void Frame::selectFrameElementInParentIfFullySelected()
2530 {
2531     // Find the parent frame; if there is none, then we have nothing to do.
2532     Frame *parent = tree()->parent();
2533     if (!parent)
2534         return;
2535     FrameView *parentView = parent->view();
2536     if (!parentView)
2537         return;
2538
2539     // Check if the selection contains the entire frame contents; if not, then there is nothing to do.
2540     if (!d->m_selection.isRange())
2541         return;
2542     if (!isStartOfDocument(VisiblePosition(d->m_selection.start(), d->m_selection.affinity())))
2543         return;
2544     if (!isEndOfDocument(VisiblePosition(d->m_selection.end(), d->m_selection.affinity())))
2545         return;
2546
2547     // Get to the <iframe> or <frame> (or even <object>) element in the parent frame.
2548     Document *doc = document();
2549     if (!doc)
2550         return;
2551     Element *ownerElement = doc->ownerElement();
2552     if (!ownerElement)
2553         return;
2554     Node *ownerElementParent = ownerElement->parentNode();
2555     if (!ownerElementParent)
2556         return;
2557         
2558     // This method's purpose is it to make it easier to select iframes (in order to delete them).  Don't do anything if the iframe isn't deletable.
2559     if (!ownerElementParent->isContentEditable())
2560         return;
2561
2562     // Create compute positions before and after the element.
2563     unsigned ownerElementNodeIndex = ownerElement->nodeIndex();
2564     VisiblePosition beforeOwnerElement(VisiblePosition(ownerElementParent, ownerElementNodeIndex, SEL_DEFAULT_AFFINITY));
2565     VisiblePosition afterOwnerElement(VisiblePosition(ownerElementParent, ownerElementNodeIndex + 1, VP_UPSTREAM_IF_POSSIBLE));
2566
2567     // Focus on the parent frame, and then select from before this element to after.
2568     if (parent->shouldChangeSelection(SelectionController(beforeOwnerElement, afterOwnerElement))) {
2569         parentView->setFocus();
2570         parent->setSelection(SelectionController(beforeOwnerElement, afterOwnerElement));
2571     }
2572 }
2573
2574 void Frame::handleFallbackContent()
2575 {
2576     Element* owner = ownerElement();
2577     if (!owner || !owner->hasTagName(objectTag))
2578         return;
2579     static_cast<HTMLObjectElement*>(owner)->renderFallbackContent();
2580 }
2581
2582 void Frame::setSettings(Settings *settings)
2583 {
2584     d->m_settings = settings;
2585 }
2586
2587 void Frame::provisionalLoadStarted()
2588 {
2589     // we don't want to wait until we get an actual http response back
2590     // to cancel pending redirects, otherwise they might fire before
2591     // that happens.
2592     cancelRedirection(true);
2593 }
2594
2595 bool Frame::userGestureHint()
2596 {
2597     Frame *rootFrame = this;
2598     while (rootFrame->tree()->parent())
2599         rootFrame = rootFrame->tree()->parent();
2600
2601     if (rootFrame->jScript())
2602         return rootFrame->jScript()->interpreter()->wasRunByUserGesture();
2603
2604     return true; // If JavaScript is disabled, a user gesture must have initiated the navigation
2605 }
2606
2607 RenderObject *Frame::renderer() const
2608 {
2609     Document *doc = document();
2610     return doc ? doc->renderer() : 0;
2611 }
2612
2613 Element* Frame::ownerElement()
2614 {
2615     return d->m_ownerElement;
2616 }
2617
2618 RenderPart* Frame::ownerRenderer()
2619 {
2620     Element* ownerElement = d->m_ownerElement;
2621     if (!ownerElement)
2622         return 0;
2623     return static_cast<RenderPart*>(ownerElement->renderer());
2624 }
2625
2626 IntRect Frame::selectionRect() const
2627 {
2628     RenderView *root = static_cast<RenderView*>(renderer());
2629     if (!root)
2630         return IntRect();
2631
2632     return root->selectionRect();
2633 }
2634
2635 // returns FloatRect because going through IntRect would truncate any floats
2636 FloatRect Frame::visibleSelectionRect() const
2637 {
2638     if (!d->m_view)
2639         return FloatRect();
2640     
2641     return intersection(selectionRect(), d->m_view->visibleContentRect());
2642 }
2643
2644 bool Frame::isFrameSet() const
2645 {
2646     Document* document = d->m_doc.get();
2647     if (!document || !document->isHTMLDocument())
2648         return false;
2649     Node *body = static_cast<HTMLDocument*>(document)->body();
2650     return body && body->renderer() && body->hasTagName(framesetTag);
2651 }
2652
2653 bool Frame::openURL(const KURL& URL)
2654 {
2655     ASSERT_NOT_REACHED();
2656     return true;
2657 }
2658
2659 void Frame::didNotOpenURL(const KURL& URL)
2660 {
2661     if (d->m_submittedFormURL == URL)
2662         d->m_submittedFormURL = KURL();
2663 }
2664
2665 // Scans logically forward from "start", including any child frames
2666 static HTMLFormElement *scanForForm(Node *start)
2667 {
2668     Node *n;
2669     for (n = start; n; n = n->traverseNextNode()) {
2670         if (n->hasTagName(formTag))
2671             return static_cast<HTMLFormElement*>(n);
2672         else if (n->isHTMLElement() && static_cast<HTMLElement*>(n)->isGenericFormElement())
2673             return static_cast<HTMLGenericFormElement*>(n)->form();
2674         else if (n->hasTagName(frameTag) || n->hasTagName(iframeTag)) {
2675             Node *childDoc = static_cast<HTMLFrameElement*>(n)->contentDocument();
2676             if (HTMLFormElement *frameResult = scanForForm(childDoc))
2677                 return frameResult;
2678         }
2679     }
2680     return 0;
2681 }
2682
2683 // We look for either the form containing the current focus, or for one immediately after it
2684 HTMLFormElement *Frame::currentForm() const
2685 {
2686     // start looking either at the active (first responder) node, or where the selection is
2687     Node *start = d->m_doc ? d->m_doc->focusNode() : 0;
2688     if (!start)
2689         start = selection().start().node();
2690     
2691     // try walking up the node tree to find a form element
2692     Node *n;
2693     for (n = start; n; n = n->parentNode()) {
2694         if (n->hasTagName(formTag))
2695             return static_cast<HTMLFormElement*>(n);
2696         else if (n->isHTMLElement()
2697                    && static_cast<HTMLElement*>(n)->isGenericFormElement())
2698             return static_cast<HTMLGenericFormElement*>(n)->form();
2699     }
2700     
2701     // try walking forward in the node tree to find a form element
2702     return start ? scanForForm(start) : 0;
2703 }
2704
2705 void Frame::setEncoding(const DeprecatedString& name, bool userChosen)
2706 {
2707     if (!d->m_workingURL.isEmpty())
2708         receivedFirstData();
2709     d->m_encoding = name;
2710     d->m_haveEncoding = userChosen;
2711 }
2712
2713 void Frame::addData(const char *bytes, int length)
2714 {
2715     ASSERT(d->m_workingURL.isEmpty());
2716     ASSERT(d->m_doc);
2717     ASSERT(d->m_doc->parsing());
2718     write(bytes, length);
2719 }
2720
2721 // FIXME: should this go in SelectionController?
2722 void Frame::revealSelection()
2723 {
2724     IntRect rect;
2725     
2726     switch (selection().state()) {
2727         case Selection::NONE:
2728             return;
2729             
2730         case Selection::CARET:
2731             rect = selection().caretRect();
2732             break;
2733             
2734         case Selection::RANGE:
2735             rect = selectionRect();
2736             break;
2737     }
2738     
2739     Position start = selection().start();
2740     Position end = selection().end();
2741     ASSERT(start.node());
2742     if (start.node() && start.node()->renderer()) {
2743         RenderLayer *layer = start.node()->renderer()->enclosingLayer();
2744         if (layer) {
2745             ASSERT(!end.node() || !end.node()->renderer() 
2746                    || (end.node()->renderer()->enclosingLayer() == layer));
2747             layer->scrollRectToVisible(rect);
2748         }
2749     }
2750 }
2751
2752 // FIXME: should this be here?
2753 bool Frame::scrollOverflow(ScrollDirection direction, ScrollGranularity granularity)
2754 {
2755     if (!document()) {
2756         return false;
2757     }
2758     
2759     Node *node = document()->focusNode();
2760     if (node == 0) {
2761         node = d->m_mousePressNode.get();
2762     }
2763     
2764     if (node != 0) {
2765         RenderObject *r = node->renderer();
2766         if (r != 0) {
2767             return r->scroll(direction, granularity);
2768         }
2769     }
2770     
2771     return false;
2772 }
2773
2774 void Frame::handleAutoscroll(RenderLayer* layer)
2775 {
2776     if (d->m_autoscrollTimer.isActive())
2777         return;
2778     d->m_autoscrollLayer = layer;
2779     startAutoscrollTimer();
2780 }
2781
2782 void Frame::autoscrollTimerFired(Timer<Frame>*)
2783 {
2784     if (!d->m_bMousePressed){
2785         stopAutoscrollTimer();
2786         return;
2787     }
2788     if (d->m_autoscrollLayer) {
2789         d->m_autoscrollLayer->autoscroll();
2790     } 
2791 }
2792
2793 RenderObject::NodeInfo Frame::nodeInfoAtPoint(const IntPoint& point, bool allowShadowContent)
2794 {
2795     RenderObject::NodeInfo nodeInfo(true, true);
2796     renderer()->layer()->hitTest(nodeInfo, point);
2797
2798     Node *n;
2799     Widget *widget = 0;
2800     IntPoint widgetPoint(point);
2801     
2802     while (true) {
2803         n = nodeInfo.innerNode();
2804         if (!n || !n->renderer() || !n->renderer()->isWidget())
2805             break;
2806         widget = static_cast<RenderWidget*>(n->renderer())->widget();
2807         if (!widget || !widget->isFrameView())
2808             break;
2809         Frame* frame = static_cast<HTMLFrameElement*>(n)->contentFrame();
2810         if (!frame || !frame->renderer())
2811             break;
2812         int absX, absY;
2813         n->renderer()->absolutePosition(absX, absY, true);
2814         FrameView *view = static_cast<FrameView*>(widget);
2815         widgetPoint.setX(widgetPoint.x() - absX + view->contentsX());
2816         widgetPoint.setY(widgetPoint.y() - absY + view->contentsY());
2817
2818         RenderObject::NodeInfo widgetNodeInfo(true, true);
2819         frame->renderer()->layer()->hitTest(widgetNodeInfo, widgetPoint);
2820         nodeInfo = widgetNodeInfo;
2821     }
2822     
2823     if (!allowShadowContent) {
2824         Node* node = nodeInfo.innerNode();
2825         if (node)
2826             node = node->shadowAncestorNode();
2827         nodeInfo.setInnerNode(node);
2828         node = nodeInfo.innerNonSharedNode();
2829         if (node)
2830             node = node->shadowAncestorNode();
2831         nodeInfo.setInnerNonSharedNode(node); 
2832     }
2833     return nodeInfo;
2834 }
2835
2836 bool Frame::hasSelection()
2837 {
2838     if (selection().isNone())
2839         return false;
2840
2841     // If a part has a selection, it should also have a document.        
2842     ASSERT(document());
2843
2844     return true;
2845 }
2846
2847 void Frame::startAutoscrollTimer()
2848 {
2849     d->m_autoscrollTimer.startRepeating(autoscrollInterval);
2850 }
2851
2852 void Frame::stopAutoscrollTimer()
2853 {
2854     d->m_autoscrollLayer = 0;
2855     d->m_autoscrollTimer.stop();
2856 }
2857
2858 // FIXME: why is this here instead of on the FrameView?
2859 void Frame::paint(GraphicsContext* p, const IntRect& rect)
2860 {
2861 #ifndef NDEBUG
2862     bool fillWithRed;
2863     if (!document() || document()->printing())
2864         fillWithRed = false; // Printing, don't fill with red (can't remember why).
2865     else if (document()->ownerElement())
2866         fillWithRed = false; // Subframe, don't fill with red.
2867     else if (view() && view()->isTransparent())
2868         fillWithRed = false; // Transparent, don't fill with red.
2869     else if (d->m_paintRestriction == PaintRestrictionSelectionOnly || d->m_paintRestriction == PaintRestrictionSelectionOnlyWhiteText)
2870         fillWithRed = false; // Selections are transparent, don't fill with red.
2871     else if (d->m_elementToDraw)
2872         fillWithRed = false; // Element images are transparent, don't fill with red.
2873     else
2874         fillWithRed = true;
2875     
2876     if (fillWithRed)
2877         p->fillRect(rect, Color(0xFF, 0, 0));
2878 #endif
2879     
2880     if (renderer()) {
2881         // d->m_elementToDraw is used to draw only one element
2882         RenderObject *eltRenderer = d->m_elementToDraw ? d->m_elementToDraw->renderer() : 0;
2883         if (d->m_paintRestriction == PaintRestrictionNone)
2884             renderer()->document()->invalidateRenderedRectsForMarkersInRect(rect);
2885         renderer()->layer()->paint(p, rect, d->m_paintRestriction, eltRenderer);
2886
2887 #if __APPLE__
2888         // Regions may have changed as a result of the visibility/z-index of element changing.
2889         if (renderer()->document()->dashboardRegionsDirty())
2890             renderer()->view()->frameView()->updateDashboardRegions();
2891 #endif
2892     } else
2893         LOG_ERROR("called Frame::paint with nil renderer");
2894 }
2895
2896 #if __APPLE__
2897
2898 void Frame::adjustPageHeight(float *newBottom, float oldTop, float oldBottom, float bottomLimit)
2899 {
2900     RenderView *root = static_cast<RenderView*>(document()->renderer());
2901     if (root) {
2902         // Use a context with painting disabled.
2903         GraphicsContext context(0);
2904         root->setTruncatedAt((int)floorf(oldBottom));
2905         IntRect dirtyRect(0, (int)floorf(oldTop), root->docWidth(), (int)ceilf(oldBottom - oldTop));
2906         root->layer()->paint(&context, dirtyRect);
2907         *newBottom = root->bestTruncatedAt();
2908         if (*newBottom == 0)
2909             *newBottom = oldBottom;
2910     } else
2911         *newBottom = oldBottom;
2912 }
2913
2914 #endif
2915
2916 PausedTimeouts *Frame::pauseTimeouts()
2917 {
2918 #ifdef SVG_SUPPORT
2919     if (d->m_doc && d->m_doc->svgExtensions())
2920         d->m_doc->accessSVGExtensions()->pauseAnimations();
2921 #endif
2922
2923     if (d->m_doc && d->m_jscript) {
2924         if (Window* w = Window::retrieveWindow(this))
2925             return w->pauseTimeouts();
2926     }
2927     return 0;
2928 }
2929
2930 void Frame::resumeTimeouts(PausedTimeouts* t)
2931 {
2932 #ifdef SVG_SUPPORT
2933     if (d->m_doc && d->m_doc->svgExtensions())
2934         d->m_doc->accessSVGExtensions()->unpauseAnimations();
2935 #endif
2936
2937     if (d->m_doc && d->m_jscript && d->m_bJScriptEnabled) {
2938         if (Window* w = Window::retrieveWindow(this))
2939             w->resumeTimeouts(t);
2940     }
2941 }
2942
2943 bool Frame::canCachePage()
2944 {
2945     // Only save page state if:
2946     // 1.  We're not a frame or frameset.
2947     // 2.  The page has no unload handler.
2948     // 3.  The page has no password fields.
2949     // 4.  The URL for the page is not https.
2950     // 5.  The page has no applets.
2951     if (tree()->childCount() || d->m_plugins.size() ||
2952         tree()->parent() ||
2953         d->m_url.protocol().startsWith("https") || 
2954         (d->m_doc && (d->m_doc->applets()->length() != 0 ||
2955                       d->m_doc->hasWindowEventListener(unloadEvent) ||
2956                       d->m_doc->hasPasswordField()))) {
2957         return false;
2958     }
2959     return true;
2960 }
2961
2962 void Frame::saveWindowProperties(KJS::SavedProperties *windowProperties)
2963 {
2964     Window *window = Window::retrieveWindow(this);
2965     if (window)
2966         window->saveProperties(*windowProperties);
2967 }
2968
2969 void Frame::saveLocationProperties(SavedProperties *locationProperties)
2970 {
2971     Window *window = Window::retrieveWindow(this);
2972     if (window) {
2973         JSLock lock;
2974         Location *location = window->location();
2975         location->saveProperties(*locationProperties);
2976     }
2977 }
2978
2979 void Frame::restoreWindowProperties(SavedProperties *windowProperties)
2980 {
2981     Window *window = Window::retrieveWindow(this);
2982     if (window)
2983         window->restoreProperties(*windowProperties);
2984 }
2985
2986 void Frame::restoreLocationProperties(SavedProperties *locationProperties)
2987 {
2988     Window *window = Window::retrieveWindow(this);
2989     if (window) {
2990         JSLock lock;
2991         Location *location = window->location();
2992         location->restoreProperties(*locationProperties);
2993     }
2994 }
2995
2996 void Frame::saveInterpreterBuiltins(SavedBuiltins& interpreterBuiltins)
2997 {
2998     if (jScript())
2999         jScript()->interpreter()->saveBuiltins(interpreterBuiltins);
3000 }
3001
3002 void Frame::restoreInterpreterBuiltins(const SavedBuiltins& interpreterBuiltins)
3003 {
3004     if (jScript())
3005         jScript()->interpreter()->restoreBuiltins(interpreterBuiltins);
3006 }
3007
3008 Frame *Frame::frameForWidget(const Widget *widget)
3009 {
3010     ASSERT_ARG(widget, widget);
3011     
3012     Node *node = nodeForWidget(widget);
3013     if (node)
3014         return frameForNode(node);
3015     
3016     // Assume all widgets are either form controls, or FrameViews.
3017     ASSERT(widget->isFrameView());
3018     return static_cast<const FrameView*>(widget)->frame();
3019 }
3020
3021 Frame *Frame::frameForNode(Node *node)
3022 {
3023     ASSERT_ARG(node, node);
3024     return node->document()->frame();
3025 }
3026
3027 Node* Frame::nodeForWidget(const Widget* widget)
3028 {
3029     ASSERT_ARG(widget, widget);
3030     WidgetClient* client = widget->client();
3031     if (!client)
3032         return 0;
3033     return client->element(const_cast<Widget*>(widget));
3034 }
3035
3036 void Frame::clearDocumentFocus(Widget *widget)
3037 {
3038     Node *node = nodeForWidget(widget);
3039     ASSERT(node);
3040     node->document()->setFocusNode(0);
3041 }
3042
3043 void Frame::updatePolicyBaseURL()
3044 {
3045     if (tree()->parent() && tree()->parent()->document())
3046         setPolicyBaseURL(tree()->parent()->document()->policyBaseURL());
3047     else
3048         setPolicyBaseURL(d->m_url.url());
3049 }
3050
3051 void Frame::setPolicyBaseURL(const String& s)
3052 {
3053     if (document())
3054         document()->setPolicyBaseURL(s);
3055     for (Frame* child = tree()->firstChild(); child; child = child->tree()->nextSibling())
3056         child->setPolicyBaseURL(s);
3057 }
3058
3059 void Frame::forceLayout()
3060 {
3061     FrameView *v = d->m_view.get();
3062     if (v) {
3063         v->layout(false);
3064         // We cannot unschedule a pending relayout, since the force can be called with
3065         // a tiny rectangle from a drawRect update.  By unscheduling we in effect
3066         // "validate" and stop the necessary full repaint from occurring.  Basically any basic
3067         // append/remove DHTML is broken by this call.  For now, I have removed the optimization
3068         // until we have a better invalidation stategy. -dwh
3069         //v->unscheduleRelayout();
3070     }
3071 }
3072
3073 void Frame::forceLayoutWithPageWidthRange(float minPageWidth, float maxPageWidth)
3074 {
3075     // Dumping externalRepresentation(m_frame->renderer()).ascii() is a good trick to see
3076     // the state of things before and after the layout
3077     RenderView *root = static_cast<RenderView*>(document()->renderer());
3078     if (root) {
3079         // This magic is basically copied from khtmlview::print
3080         int pageW = (int)ceilf(minPageWidth);
3081         root->setWidth(pageW);
3082         root->setNeedsLayoutAndMinMaxRecalc();
3083         forceLayout();
3084         
3085         // If we don't fit in the minimum page width, we'll lay out again. If we don't fit in the
3086         // maximum page width, we will lay out to the maximum page width and clip extra content.
3087         // FIXME: We are assuming a shrink-to-fit printing implementation.  A cropping
3088         // implementation should not do this!
3089         int rightmostPos = root->rightmostPosition();
3090         if (rightmostPos > minPageWidth) {
3091             pageW = min(rightmostPos, (int)ceilf(maxPageWidth));
3092             root->setWidth(pageW);
3093             root->setNeedsLayoutAndMinMaxRecalc();
3094             forceLayout();
3095         }
3096     }
3097 }
3098
3099 void Frame::sendResizeEvent()
3100 {
3101     if (Document* doc = document())
3102         doc->dispatchWindowEvent(EventNames::resizeEvent, false, false);
3103 }
3104
3105 void Frame::sendScrollEvent()
3106 {
3107     FrameView *v = d->m_view.get();
3108     if (v) {
3109         Document *doc = document();
3110         if (!doc)
3111             return;
3112         doc->dispatchHTMLEvent(scrollEvent, true, false);
3113     }
3114 }
3115
3116 bool Frame::scrollbarsVisible()
3117 {
3118     if (!view())
3119         return false;
3120     
3121     if (view()->hScrollBarMode() == ScrollBarAlwaysOff || view()->vScrollBarMode() == ScrollBarAlwaysOff)
3122         return false;
3123     
3124     return true;
3125 }
3126
3127 void Frame::addMetaData(const String& key, const String& value)
3128 {
3129     d->m_metaData.set(key, value);
3130 }
3131
3132 // This does the same kind of work that Frame::openURL does, except it relies on the fact
3133 // that a higher level already checked that the URLs match and the scrolling is the right thing to do.
3134 void Frame::scrollToAnchor(const KURL& URL)
3135 {
3136     d->m_url = URL;
3137     started();
3138     
3139     gotoAnchor();
3140     
3141     // It's important to model this as a load that starts and immediately finishes.
3142     // Otherwise, the parent frame may think we never finished loading.
3143     d->m_bComplete = false;
3144     checkCompleted();
3145 }
3146
3147 bool Frame::closeURL()
3148 {
3149     saveDocumentState();
3150     stopLoading(true);
3151     clearUndoRedoOperations();
3152     return true;
3153 }
3154
3155 bool Frame::canMouseDownStartSelect(Node* node)
3156 {
3157     if (!node || !node->renderer())
3158         return true;
3159     
3160     // Check to see if -webkit-user-select has been set to none
3161     if (!node->renderer()->canSelect())
3162         return false;
3163     
3164     // Some controls and images can't start a select on a mouse down.
3165     for (RenderObject* curr = node->renderer(); curr; curr = curr->parent()) {
3166         if (curr->style()->userSelect() == SELECT_IGNORE)
3167             return false;
3168     }
3169     
3170     return true;
3171 }
3172
3173 void Frame::handleMouseReleaseDoubleClickEvent(const MouseEventWithHitTestResults& event)
3174 {
3175     passWidgetMouseDownEventToWidget(event, true);
3176 }
3177
3178 bool Frame::passWidgetMouseDownEventToWidget(const MouseEventWithHitTestResults& event, bool isDoubleClick)
3179 {
3180     // Figure out which view to send the event to.
3181     RenderObject *target = event.targetNode() ? event.targetNode()->renderer() : 0;
3182     if (!target)
3183         return false;
3184     
3185     Widget* widget = RenderLayer::gScrollBar;
3186     if (!widget) {
3187         if (!target->isWidget())
3188             return false;
3189         widget = static_cast<RenderWidget*>(target)->widget();
3190     }
3191     
3192     // Doubleclick events don't exist in Cocoa.  Since passWidgetMouseDownEventToWidget will
3193     // just pass _currentEvent down to the widget,  we don't want to call it for events that
3194     // don't correspond to Cocoa events.  The mousedown/ups will have already been passed on as
3195     // part of the pressed/released handling.
3196     if (!isDoubleClick)
3197         return passMouseDownEventToWidget(widget);
3198     return true;
3199 }
3200
3201 bool Frame::passWidgetMouseDownEventToWidget(RenderWidget *renderWidget)
3202 {
3203     return passMouseDownEventToWidget(renderWidget->widget());
3204 }
3205
3206 void Frame::clearTimers(FrameView *view)
3207 {
3208     if (view) {
3209         view->unscheduleRelayout();
3210         if (view->frame()) {
3211             Document* document = view->frame()->document();
3212             if (document && document->renderer() && document->renderer()->layer())
3213                 document->renderer()->layer()->suspendMarquees();
3214         }
3215     }
3216 }
3217
3218 void Frame::clearTimers()
3219 {
3220     clearTimers(d->m_view.get());
3221 }
3222
3223 // FIXME: selection controller?
3224 void Frame::centerSelectionInVisibleArea() const
3225 {
3226     IntRect rect;
3227     
3228     switch (selection().state()) {
3229         case Selection::NONE:
3230             return;
3231             
3232         case Selection::CARET:
3233             rect = selection().caretRect();
3234             break;
3235             
3236         case Selection::RANGE:
3237             rect = selectionRect();
3238             break;
3239     }
3240     
3241     Position start = selection().start();
3242     Position end = selection().end();
3243     ASSERT(start.node());
3244     if (start.node() && start.node()->renderer()) {
3245         RenderLayer *layer = start.node()->renderer()->enclosingLayer();
3246         if (layer) {
3247             ASSERT(!end.node() || !end.node()->renderer() 
3248                    || (end.node()->renderer()->enclosingLayer() == layer));
3249             layer->scrollRectToVisible(rect, RenderLayer::gAlignCenterAlways, RenderLayer::gAlignCenterAlways);
3250         }
3251     }
3252 }
3253
3254 RenderStyle *Frame::styleForSelectionStart(Node *&nodeToRemove) const
3255 {
3256     nodeToRemove = 0;
3257     
3258     if (!document())
3259         return 0;
3260     if (d->m_selection.isNone())
3261         return 0;
3262     
3263     Position pos = VisiblePosition(d->m_selection.start(), d->m_selection.affinity()).deepEquivalent();
3264     if (!pos.inRenderedContent())
3265         return 0;
3266     Node *node = pos.node();
3267     if (!node)
3268         return 0;
3269     
3270     if (!d->m_typingStyle)
3271         return node->renderer()->style();
3272     
3273     ExceptionCode ec = 0;
3274     RefPtr<Element> styleElement = document()->createElementNS(xhtmlNamespaceURI, "span", ec);
3275     ASSERT(ec == 0);
3276     
3277     styleElement->setAttribute(styleAttr, d->m_typingStyle->cssText().impl(), ec);
3278     ASSERT(ec == 0);
3279     
3280     styleElement->appendChild(document()->createEditingTextNode(""), ec);
3281     ASSERT(ec == 0);
3282     
3283     node->parentNode()->appendChild(styleElement, ec);
3284     ASSERT(ec == 0);
3285     
3286     nodeToRemove = styleElement.get();    
3287     return styleElement->renderer()->style();
3288 }
3289
3290 void Frame::setMediaType(const String& type)
3291 {
3292     if (d->m_view)
3293         d->m_view->setMediaType(type);
3294 }
3295
3296 void Frame::setSelectionFromNone()
3297 {
3298     // Put a caret inside the body if the entire frame is editable (either the 
3299     // entire WebView is editable or designMode is on for this document).
3300     Document *doc = document();
3301     if (!doc || !selection().isNone() || !isContentEditable())
3302         return;
3303         
3304     Node* node = doc->documentElement();
3305     while (node && !node->hasTagName(bodyTag))
3306         node = node->traverseNextNode();
3307     if (node)
3308         setSelection(SelectionController(Position(node, 0), DOWNSTREAM));
3309 }
3310
3311 bool Frame::isActive() const
3312 {
3313     return d->m_isActive;
3314 }
3315
3316 void Frame::setIsActive(bool flag)
3317 {
3318     if (d->m_isActive == flag)
3319         return;
3320     
3321     d->m_isActive = flag;
3322
3323     // This method does the job of updating the view based on whether the view is "active".
3324     // This involves three kinds of drawing updates:
3325
3326     // 1. The background color used to draw behind selected content (active | inactive color)
3327     if (d->m_view)
3328         d->m_view->updateContents(enclosingIntRect(visibleSelectionRect()));
3329
3330     // 2. Caret blinking (blinks | does not blink)
3331     if (flag)
3332         setSelectionFromNone();
3333     setCaretVisible(flag);
3334     
3335     // 3. The drawing of a focus ring around links in web pages.
3336     Document *doc = document();
3337     if (doc) {
3338         Node *node = doc->focusNode();
3339         if (node) {
3340             node->setChanged();
3341             if (node->renderer() && node->renderer()->style()->hasAppearance())
3342                 theme()->stateChanged(node->renderer(), FocusState);
3343         }
3344     }
3345     
3346     // 4, Changing the tint of controls from clear to aqua/graphite and vice versa.  We
3347     // do a "fake" paint.  When the theme gets a paint call, it can then do an invalidate.  This is only
3348     // done if the theme supports control tinting.
3349     if (doc && d->m_view && theme()->supportsControlTints() && renderer()) {
3350         doc->updateLayout(); // Ensure layout is up to date.
3351         IntRect visibleRect(enclosingIntRect(d->m_view->visibleContentRect()));
3352         GraphicsContext context((PlatformGraphicsContext*)0);
3353         context.setUpdatingControlTints(true);
3354         paint(&context, visibleRect);
3355     }
3356 }
3357
3358 void Frame::setWindowHasFocus(bool flag)
3359 {
3360     if (d->m_windowHasFocus == flag)
3361         return;
3362     d->m_windowHasFocus = flag;
3363     
3364     if (Document *doc = document())
3365         doc->dispatchWindowEvent(flag ? focusEvent : blurEvent, false, false);
3366 }
3367
3368 bool Frame::inViewSourceMode() const
3369 {
3370     return d->m_inViewSourceMode;
3371 }
3372
3373 void Frame::setInViewSourceMode(bool mode) const
3374 {
3375     d->m_inViewSourceMode = mode;
3376 }
3377   
3378 UChar Frame::backslashAsCurrencySymbol() const
3379 {
3380     Document *doc = document();
3381     if (!doc)
3382         return '\\';
3383     Decoder *decoder = doc->decoder();
3384     if (!decoder)
3385         return '\\';
3386
3387     return decoder->encoding().backslashAsCurrencySymbol();
3388 }
3389
3390 bool Frame::markedTextUsesUnderlines() const
3391 {
3392     return d->m_markedTextUsesUnderlines;
3393 }
3394
3395 DeprecatedValueList<MarkedTextUnderline> Frame::markedTextUnderlines() const
3396 {
3397     return d->m_markedTextUnderlines;
3398 }
3399
3400 // Searches from the beginning of the document if nothing is selected.
3401 bool Frame::findString(const String& target, bool forward, bool caseFlag, bool wrapFlag)
3402 {
3403     if (target.isEmpty())
3404         return false;
3405     
3406     // Initially search from the start (if forward) or end (if backward) of the selection, and search to edge of document.
3407     RefPtr<Range> searchRange(rangeOfContents(document()));
3408     if (selection().start().node()) {
3409         if (forward)
3410             setStart(searchRange.get(), VisiblePosition(selection().start(), selection().affinity()));
3411         else
3412             setEnd(searchRange.get(), VisiblePosition(selection().end(), selection().affinity()));
3413     }
3414     RefPtr<Range> resultRange(findPlainText(searchRange.get(), target, forward, caseFlag));
3415     Selection sel = selection().selection();
3416     // If the found range is already selected, find again.
3417     // Build a selection with the found range to remove collapsed whitespace.
3418     // Compare ranges instead of selection objects to ignore the way that the current selection was made.
3419     if (!sel.isNone() && *Selection(resultRange.get()).toRange() == *sel.toRange()) {
3420         searchRange = rangeOfContents(document());
3421         if (forward)
3422             setStart(searchRange.get(), VisiblePosition(sel.end(), sel.affinity()));
3423         else
3424             setEnd(searchRange.get(), VisiblePosition(sel.start(), sel.affinity()));
3425         resultRange = findPlainText(searchRange.get(), target, forward, caseFlag);
3426     }
3427     
3428     int exception = 0;
3429     
3430     // If we didn't find anything and we're wrapping, search again in the entire document (this will
3431     // redundantly re-search the area already searched in some cases).
3432     if (resultRange->collapsed(exception) && wrapFlag) {
3433         searchRange = rangeOfContents(document());
3434         resultRange = findPlainText(searchRange.get(), target, forward, caseFlag);
3435         // We used to return false here if we ended up with the same range that we started with
3436         // (e.g., the selection was already the only instance of this text). But we decided that
3437         // this should be a success case instead, so we'll just fall through in that case.
3438     }
3439
3440     if (resultRange->collapsed(exception))
3441         return false;
3442
3443     setSelection(SelectionController(resultRange.get(), DOWNSTREAM));
3444     revealSelection();
3445     return true;
3446 }
3447
3448 unsigned Frame::markAllMatchesForText(const String& target, bool caseFlag)
3449 {
3450     if (target.isEmpty())
3451         return 0;
3452     
3453     RefPtr<Range> searchRange(rangeOfContents(document()));
3454     
3455     int exception = 0;
3456     unsigned matchCount = 0;
3457     do {
3458         RefPtr<Range> resultRange(findPlainText(searchRange.get(), target, true, caseFlag));
3459         if (resultRange->collapsed(exception))
3460             break;
3461         
3462         // A non-collapsed result range can in some funky whitespace cases still not
3463         // advance the range's start position (4509328). Break to avoid infinite loop.
3464         VisiblePosition newStart = endVisiblePosition(resultRange.get(), DOWNSTREAM);
3465         if (newStart == startVisiblePosition(searchRange.get(), DOWNSTREAM))
3466             break;
3467
3468         ++matchCount;
3469         document()->addMarker(resultRange.get(), DocumentMarker::TextMatch);        
3470         
3471         setStart(searchRange.get(), newStart);
3472     } while (true);
3473     
3474     // Do a "fake" paint in order to execute the code that computes the rendered rect for 
3475     // each text match.
3476     Document* doc = document();
3477     if (doc && d->m_view && renderer()) {
3478         doc->updateLayout(); // Ensure layout is up to date.
3479         IntRect visibleRect(enclosingIntRect(d->m_view->visibleContentRect()));
3480         GraphicsContext context((PlatformGraphicsContext*)0);
3481         context.setPaintingDisabled(true);
3482         paint(&context, visibleRect);
3483     }
3484     
3485     return matchCount;
3486 }
3487
3488 bool Frame::markedTextMatchesAreHighlighted() const
3489 {
3490     return d->m_highlightTextMatches;
3491 }
3492
3493 void Frame::setMarkedTextMatchesAreHighlighted(bool flag)
3494 {
3495     if (flag == d->m_highlightTextMatches)
3496         return;
3497     
3498     d->m_highlightTextMatches = flag;
3499     document()->repaintMarkers(DocumentMarker::TextMatch);
3500 }
3501
3502 void Frame::prepareForUserAction()
3503 {
3504     // Reset the multiple form submission protection code.
3505     // We'll let you submit the same form twice if you do two separate user actions.
3506     d->m_submittedFormURL = KURL();
3507 }
3508
3509 Node *Frame::mousePressNode()
3510 {
3511     return d->m_mousePressNode.get();
3512 }
3513
3514 bool Frame::isComplete() const
3515 {
3516     return d->m_bComplete;
3517 }
3518
3519 bool Frame::isLoadingMainResource() const
3520 {
3521     return d->m_bLoadingMainResource;
3522 }
3523
3524 FrameTree* Frame::tree() const
3525 {
3526     return &d->m_treeNode;
3527 }
3528
3529 DOMWindow* Frame::domWindow() const
3530 {
3531     if (!d->m_domWindow)
3532         d->m_domWindow = new DOMWindow(const_cast<Frame*>(this));
3533
3534     return d->m_domWindow.get();
3535 }
3536
3537 KURL Frame::url() const
3538 {
3539     return d->m_url;
3540 }
3541
3542 void Frame::startRedirectionTimer()
3543 {
3544     d->m_redirectionTimer.startOneShot(d->m_delayRedirect);
3545 }
3546
3547 void Frame::stopRedirectionTimer()
3548 {
3549     d->m_redirectionTimer.stop();
3550 }
3551
3552 void Frame::frameDetached()
3553 {
3554 }
3555
3556 void Frame::updateBaseURLForEmptyDocument()
3557 {
3558     Element* owner = ownerElement();
3559     // FIXME: Should embed be included?
3560     if (owner && (owner->hasTagName(iframeTag) || owner->hasTagName(objectTag) || owner->hasTagName(embedTag)))
3561         d->m_doc->setBaseURL(tree()->parent()->d->m_doc->baseURL());
3562 }
3563
3564 Page* Frame::page() const
3565 {
3566     return d->m_page;
3567 }
3568
3569 void Frame::pageDestroyed()
3570 {
3571     d->m_page = 0;
3572
3573     // This will stop any JS timers
3574     if (d->m_jscript && d->m_jscript->haveInterpreter())
3575         if (Window* w = Window::retrieveWindow(this))
3576             w->disconnectFrame();
3577 }
3578
3579 void Frame::completed(bool complete)
3580 {
3581     ref();
3582     for (Frame* child = tree()->firstChild(); child; child = child->tree()->nextSibling())
3583         child->parentCompleted();
3584     if (Frame* parent = tree()->parent())
3585         parent->childCompleted(complete);
3586     submitFormAgain();
3587     deref();
3588 }
3589
3590 void Frame::setStatusBarText(const String&)
3591 {
3592 }
3593
3594 void Frame::started()
3595 {
3596     for (Frame* frame = this; frame; frame = frame->tree()->parent())
3597         frame->d->m_bComplete = false;
3598 }
3599
3600 void Frame::disconnectOwnerElement()
3601 {
3602     if (d->m_ownerElement)
3603         d->m_page->decrementFrameCount();
3604         
3605     d->m_ownerElement = 0;
3606 }
3607
3608 String Frame::documentTypeString() const
3609 {
3610     if (Document *doc = document())
3611         if (DocumentType *doctype = doc->realDocType())
3612             return doctype->toString();
3613
3614     return String();
3615 }
3616
3617 bool Frame::containsPlugins() const 
3618
3619     return d->m_plugins.size() != 0;
3620 }
3621
3622 bool Frame::prohibitsScrolling() const
3623 {
3624     return d->m_prohibitsScrolling;
3625 }
3626
3627 void Frame::setProhibitsScrolling(const bool prohibit)
3628 {
3629     d->m_prohibitsScrolling = prohibit;
3630 }
3631
3632 } // namespace WebCore