LayoutTests:
[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     notifyRendererOfSelectionChange(true);
1968 }
1969
1970 bool Frame::selectContentsOfNode(Node* node)
1971 {
1972     SelectionController sel = SelectionController(Selection::selectionFromContentsOfNode(node));    
1973     if (shouldChangeSelection(sel)) {
1974         setSelection(sel);
1975         return true;
1976     }
1977     return false;
1978 }
1979
1980 bool Frame::shouldChangeSelection(const SelectionController& newselection) const
1981 {
1982     return shouldChangeSelection(d->m_selection, newselection, newselection.affinity(), false);
1983 }
1984
1985 bool Frame::shouldDeleteSelection(const SelectionController& newselection) const
1986 {
1987     return true;
1988 }
1989
1990 bool Frame::shouldBeginEditing(const Range *range) const
1991 {
1992     return true;
1993 }
1994
1995 bool Frame::shouldEndEditing(const Range *range) const
1996 {
1997     return true;
1998 }
1999
2000 bool Frame::isContentEditable() const 
2001 {
2002     if (!d->m_doc)
2003         return false;
2004     return d->m_doc->inDesignMode();
2005 }
2006
2007 void Frame::textFieldDidBeginEditing(Element* input)
2008 {
2009 }
2010
2011 void Frame::textFieldDidEndEditing(Element* input)
2012 {
2013 }
2014
2015 void Frame::textDidChangeInTextField(Element* input)
2016 {
2017 }
2018
2019 bool Frame::doTextFieldCommandFromEvent(Element* input, const PlatformKeyboardEvent* evt)
2020 {
2021     return false;
2022 }
2023
2024 void Frame::textWillBeDeletedInTextField(Element* input)
2025 {
2026 }
2027
2028 void Frame::textDidChangeInTextArea(Element* input)
2029 {
2030 }
2031
2032 EditCommandPtr Frame::lastEditCommand()
2033 {
2034     return d->m_lastEditCommand;
2035 }
2036
2037 void dispatchEditableContentChangedEvent(Node* root)
2038 {
2039     if (!root)
2040         return;
2041         
2042     ExceptionCode ec = 0;
2043     EventTargetNodeCast(root)->dispatchEvent(new Event(khtmlEditableContentChangedEvent, false, false), ec, true);
2044 }
2045
2046 void Frame::appliedEditing(EditCommandPtr& cmd)
2047 {
2048     SelectionController sel(cmd.endingSelection());
2049     if (shouldChangeSelection(sel))
2050         setSelection(sel, false);
2051     
2052     dispatchEditableContentChangedEvent(!selection().isNone() ? selection().start().node()->rootEditableElement() : 0);
2053
2054     // Now set the typing style from the command. Clear it when done.
2055     // This helps make the case work where you completely delete a piece
2056     // of styled text and then type a character immediately after.
2057     // That new character needs to take on the style of the just-deleted text.
2058     // FIXME: Improve typing style.
2059     // See this bug: <rdar://problem/3769899> Implementation of typing style needs improvement
2060     if (cmd.typingStyle()) {
2061         setTypingStyle(cmd.typingStyle());
2062         cmd.setTypingStyle(0);
2063     }
2064
2065     // Command will be equal to last edit command only in the case of typing
2066     if (d->m_lastEditCommand == cmd) {
2067         assert(cmd.isTypingCommand());
2068     }
2069     else {
2070         // Only register a new undo command if the command passed in is
2071         // different from the last command
2072         registerCommandForUndo(cmd);
2073         d->m_lastEditCommand = cmd;
2074     }
2075     respondToChangedContents();
2076 }
2077
2078 void Frame::unappliedEditing(EditCommandPtr& cmd)
2079 {
2080     SelectionController sel(cmd.startingSelection());
2081     if (shouldChangeSelection(sel))
2082         setSelection(sel, true);
2083     
2084     dispatchEditableContentChangedEvent(!selection().isNone() ? selection().start().node()->rootEditableElement() : 0);
2085         
2086     registerCommandForRedo(cmd);
2087     respondToChangedContents();
2088     d->m_lastEditCommand = EditCommandPtr::emptyCommand();
2089 }
2090
2091 void Frame::reappliedEditing(EditCommandPtr& cmd)
2092 {
2093     SelectionController sel(cmd.endingSelection());
2094     if (shouldChangeSelection(sel))
2095         setSelection(sel, true);
2096     
2097     dispatchEditableContentChangedEvent(!selection().isNone() ? selection().start().node()->rootEditableElement() : 0);
2098         
2099     registerCommandForUndo(cmd);
2100     respondToChangedContents();
2101     d->m_lastEditCommand = EditCommandPtr::emptyCommand();
2102 }
2103
2104 CSSMutableStyleDeclaration *Frame::typingStyle() const
2105 {
2106     return d->m_typingStyle.get();
2107 }
2108
2109 void Frame::setTypingStyle(CSSMutableStyleDeclaration *style)
2110 {
2111     d->m_typingStyle = style;
2112 }
2113
2114 void Frame::clearTypingStyle()
2115 {
2116     d->m_typingStyle = 0;
2117 }
2118
2119 JSValue* Frame::executeScript(const String& filename, int baseLine, Node* n, const DeprecatedString& script)
2120 {
2121   // FIXME: This is missing stuff that the other executeScript has.
2122   // --> d->m_runningScripts and submitFormAgain.
2123   // Why is that OK?
2124   KJSProxy *proxy = jScript();
2125   if (!proxy)
2126     return 0;
2127   JSValue* ret = proxy->evaluate(filename, baseLine, script, n);
2128   Document::updateDocumentsRendering();
2129   return ret;
2130 }
2131
2132 Frame *Frame::opener()
2133 {
2134     return d->m_opener;
2135 }
2136
2137 void Frame::setOpener(Frame* opener)
2138 {
2139     if (d->m_opener)
2140         d->m_opener->d->m_openedFrames.remove(this);
2141     if (opener)
2142         opener->d->m_openedFrames.add(this);
2143     d->m_opener = opener;
2144 }
2145
2146 bool Frame::openedByJS()
2147 {
2148     return d->m_openedByJS;
2149 }
2150
2151 void Frame::setOpenedByJS(bool _openedByJS)
2152 {
2153     d->m_openedByJS = _openedByJS;
2154 }
2155
2156 bool Frame::tabsToLinks() const
2157 {
2158     return true;
2159 }
2160
2161 bool Frame::tabsToAllControls() const
2162 {
2163     return true;
2164 }
2165
2166 void Frame::copyToPasteboard()
2167 {
2168     issueCopyCommand();
2169 }
2170
2171 void Frame::cutToPasteboard()
2172 {
2173     issueCutCommand();
2174 }
2175
2176 void Frame::pasteFromPasteboard()
2177 {
2178     issuePasteCommand();
2179 }
2180
2181 void Frame::pasteAndMatchStyle()
2182 {
2183     issuePasteAndMatchStyleCommand();
2184 }
2185
2186 void Frame::transpose()
2187 {
2188     issueTransposeCommand();
2189 }
2190
2191 void Frame::redo()
2192 {
2193     issueRedoCommand();
2194 }
2195
2196 void Frame::undo()
2197 {
2198     issueUndoCommand();
2199 }
2200
2201
2202 void Frame::computeAndSetTypingStyle(CSSStyleDeclaration *style, EditAction editingAction)
2203 {
2204     if (!style || style->length() == 0) {
2205         clearTypingStyle();
2206         return;
2207     }
2208
2209     // Calculate the current typing style.
2210     RefPtr<CSSMutableStyleDeclaration> mutableStyle = style->makeMutable();
2211     if (typingStyle()) {
2212         typingStyle()->merge(mutableStyle.get());
2213         mutableStyle = typingStyle();
2214     }
2215
2216     Node *node = VisiblePosition(selection().start(), selection().affinity()).deepEquivalent().node();
2217     CSSComputedStyleDeclaration computedStyle(node);
2218     computedStyle.diff(mutableStyle.get());
2219     
2220     // Handle block styles, substracting these from the typing style.
2221     RefPtr<CSSMutableStyleDeclaration> blockStyle = mutableStyle->copyBlockProperties();
2222     blockStyle->diff(mutableStyle.get());
2223     if (document() && blockStyle->length() > 0) {
2224         EditCommandPtr cmd(new ApplyStyleCommand(document(), blockStyle.get(), editingAction));
2225         cmd.apply();
2226     }
2227     
2228     // Set the remaining style as the typing style.
2229     d->m_typingStyle = mutableStyle.release();
2230 }
2231
2232 void Frame::applyStyle(CSSStyleDeclaration *style, EditAction editingAction)
2233 {
2234     switch (selection().state()) {
2235         case Selection::NONE:
2236             // do nothing
2237             break;
2238         case Selection::CARET: {
2239             computeAndSetTypingStyle(style, editingAction);
2240             break;
2241         }
2242         case Selection::RANGE:
2243             if (document() && style) {
2244                 EditCommandPtr cmd(new ApplyStyleCommand(document(), style, editingAction));
2245                 cmd.apply();
2246             }
2247             break;
2248     }
2249 }
2250
2251 void Frame::applyParagraphStyle(CSSStyleDeclaration *style, EditAction editingAction)
2252 {
2253     switch (selection().state()) {
2254         case Selection::NONE:
2255             // do nothing
2256             break;
2257         case Selection::CARET:
2258         case Selection::RANGE:
2259             if (document() && style) {
2260                 EditCommandPtr cmd(new ApplyStyleCommand(document(), style, editingAction, ApplyStyleCommand::ForceBlockProperties));
2261                 cmd.apply();
2262             }
2263             break;
2264     }
2265 }
2266
2267 static void updateState(CSSMutableStyleDeclaration *desiredStyle, CSSComputedStyleDeclaration *computedStyle, bool& atStart, Frame::TriState& state)
2268 {
2269     DeprecatedValueListConstIterator<CSSProperty> end;
2270     for (DeprecatedValueListConstIterator<CSSProperty> it = desiredStyle->valuesIterator(); it != end; ++it) {
2271         int propertyID = (*it).id();
2272         String desiredProperty = desiredStyle->getPropertyValue(propertyID);
2273         String computedProperty = computedStyle->getPropertyValue(propertyID);
2274         Frame::TriState propertyState = equalIgnoringCase(desiredProperty, computedProperty)
2275             ? Frame::trueTriState : Frame::falseTriState;
2276         if (atStart) {
2277             state = propertyState;
2278             atStart = false;
2279         } else if (state != propertyState) {
2280             state = Frame::mixedTriState;
2281             break;
2282         }
2283     }
2284 }
2285
2286 Frame::TriState Frame::selectionListState() const
2287 {
2288     TriState state = falseTriState;
2289
2290     if (!d->m_selection.isRange()) {
2291         Node* selectionNode = d->m_selection.selection().start().node();
2292         if (enclosingList(selectionNode))
2293             return trueTriState;
2294     } else {
2295         //FIXME: Support ranges
2296     }
2297
2298     return state;
2299 }
2300
2301 Frame::TriState Frame::selectionHasStyle(CSSStyleDeclaration *style) const
2302 {
2303     bool atStart = true;
2304     TriState state = falseTriState;
2305
2306     RefPtr<CSSMutableStyleDeclaration> mutableStyle = style->makeMutable();
2307
2308     if (!d->m_selection.isRange()) {
2309         Node* nodeToRemove;
2310         RefPtr<CSSComputedStyleDeclaration> selectionStyle = selectionComputedStyle(nodeToRemove);
2311         if (!selectionStyle)
2312             return falseTriState;
2313         updateState(mutableStyle.get(), selectionStyle.get(), atStart, state);
2314         if (nodeToRemove) {
2315             ExceptionCode ec = 0;
2316             nodeToRemove->remove(ec);
2317             assert(ec == 0);
2318         }
2319     } else {
2320         for (Node* node = d->m_selection.start().node(); node; node = node->traverseNextNode()) {
2321             RefPtr<CSSComputedStyleDeclaration> computedStyle = new CSSComputedStyleDeclaration(node);
2322             if (computedStyle)
2323                 updateState(mutableStyle.get(), computedStyle.get(), atStart, state);
2324             if (state == mixedTriState)
2325                 break;
2326             if (node == d->m_selection.end().node())
2327                 break;
2328         }
2329     }
2330
2331     return state;
2332 }
2333
2334 bool Frame::selectionStartHasStyle(CSSStyleDeclaration *style) const
2335 {
2336     Node* nodeToRemove;
2337     RefPtr<CSSStyleDeclaration> selectionStyle = selectionComputedStyle(nodeToRemove);
2338     if (!selectionStyle)
2339         return false;
2340
2341     RefPtr<CSSMutableStyleDeclaration> mutableStyle = style->makeMutable();
2342
2343     bool match = true;
2344     DeprecatedValueListConstIterator<CSSProperty> end;
2345     for (DeprecatedValueListConstIterator<CSSProperty> it = mutableStyle->valuesIterator(); it != end; ++it) {
2346         int propertyID = (*it).id();
2347         if (!equalIgnoringCase(mutableStyle->getPropertyValue(propertyID), selectionStyle->getPropertyValue(propertyID))) {
2348             match = false;
2349             break;
2350         }
2351     }
2352
2353     if (nodeToRemove) {
2354         ExceptionCode ec = 0;
2355         nodeToRemove->remove(ec);
2356         assert(ec == 0);
2357     }
2358
2359     return match;
2360 }
2361
2362 String Frame::selectionStartStylePropertyValue(int stylePropertyID) const
2363 {
2364     Node *nodeToRemove;
2365     RefPtr<CSSStyleDeclaration> selectionStyle = selectionComputedStyle(nodeToRemove);
2366     if (!selectionStyle)
2367         return String();
2368
2369     String value = selectionStyle->getPropertyValue(stylePropertyID);
2370
2371     if (nodeToRemove) {
2372         ExceptionCode ec = 0;
2373         nodeToRemove->remove(ec);
2374         assert(ec == 0);
2375     }
2376
2377     return value;
2378 }
2379
2380 CSSComputedStyleDeclaration *Frame::selectionComputedStyle(Node *&nodeToRemove) const
2381 {
2382     nodeToRemove = 0;
2383
2384     if (!document())
2385         return 0;
2386
2387     if (d->m_selection.isNone())
2388         return 0;
2389
2390     RefPtr<Range> range(d->m_selection.toRange());
2391     Position pos = range->editingStartPosition();
2392
2393     Element *elem = pos.element();
2394     if (!elem)
2395         return 0;
2396     
2397     RefPtr<Element> styleElement = elem;
2398     ExceptionCode ec = 0;
2399
2400     if (d->m_typingStyle) {
2401         styleElement = document()->createElementNS(xhtmlNamespaceURI, "span", ec);
2402         assert(ec == 0);
2403
2404         styleElement->setAttribute(styleAttr, d->m_typingStyle->cssText().impl(), ec);
2405         assert(ec == 0);
2406         
2407         styleElement->appendChild(document()->createEditingTextNode(""), ec);
2408         assert(ec == 0);
2409
2410         if (elem->renderer() && elem->renderer()->canHaveChildren()) {
2411             elem->appendChild(styleElement, ec);
2412         } else {
2413             Node *parent = elem->parent();
2414             Node *next = elem->nextSibling();
2415
2416             if (next) {
2417                 parent->insertBefore(styleElement, next, ec);
2418             } else {
2419                 parent->appendChild(styleElement, ec);
2420             }
2421         }
2422         assert(ec == 0);
2423
2424         nodeToRemove = styleElement.get();
2425     }
2426
2427     return new CSSComputedStyleDeclaration(styleElement);
2428 }
2429
2430 void Frame::applyEditingStyleToBodyElement() const
2431 {
2432     if (!d->m_doc)
2433         return;
2434         
2435     RefPtr<NodeList> list = d->m_doc->getElementsByTagName("body");
2436     unsigned len = list->length();
2437     for (unsigned i = 0; i < len; i++) {
2438         applyEditingStyleToElement(static_cast<Element*>(list->item(i)));    
2439     }
2440 }
2441
2442 void Frame::removeEditingStyleFromBodyElement() const
2443 {
2444     if (!d->m_doc)
2445         return;
2446         
2447     RefPtr<NodeList> list = d->m_doc->getElementsByTagName("body");
2448     unsigned len = list->length();
2449     for (unsigned i = 0; i < len; i++) {
2450         removeEditingStyleFromElement(static_cast<Element*>(list->item(i)));    
2451     }
2452 }
2453
2454 void Frame::applyEditingStyleToElement(Element* element) const
2455 {
2456     if (!element)
2457         return;
2458
2459     CSSStyleDeclaration* style = element->style();
2460     ASSERT(style);
2461
2462     ExceptionCode ec = 0;
2463     style->setProperty(CSS_PROP_WORD_WRAP, "break-word", false, ec);
2464     ASSERT(ec == 0);
2465     style->setProperty(CSS_PROP__WEBKIT_NBSP_MODE, "space", false, ec);
2466     ASSERT(ec == 0);
2467     style->setProperty(CSS_PROP__WEBKIT_LINE_BREAK, "after-white-space", false, ec);
2468     ASSERT(ec == 0);
2469 }
2470
2471 void Frame::removeEditingStyleFromElement(Element*) const
2472 {
2473 }
2474
2475 bool Frame::isCharacterSmartReplaceExempt(const DeprecatedChar&, bool)
2476 {
2477     // no smart replace
2478     return true;
2479 }
2480
2481 #ifndef NDEBUG
2482 static HashSet<Frame*> lifeSupportSet;
2483 #endif
2484
2485 void Frame::endAllLifeSupport()
2486 {
2487 #ifndef NDEBUG
2488     HashSet<Frame*> lifeSupportCopy = lifeSupportSet;
2489     HashSet<Frame*>::iterator end = lifeSupportCopy.end();
2490     for (HashSet<Frame*>::iterator it = lifeSupportCopy.begin(); it != end; ++it)
2491         (*it)->endLifeSupport();
2492 #endif
2493 }
2494
2495 void Frame::keepAlive()
2496 {
2497     if (d->m_lifeSupportTimer.isActive())
2498         return;
2499     ref();
2500 #ifndef NDEBUG
2501     lifeSupportSet.add(this);
2502 #endif
2503     d->m_lifeSupportTimer.startOneShot(0);
2504 }
2505
2506 void Frame::endLifeSupport()
2507 {
2508     if (!d->m_lifeSupportTimer.isActive())
2509         return;
2510     d->m_lifeSupportTimer.stop();
2511 #ifndef NDEBUG
2512     lifeSupportSet.remove(this);
2513 #endif
2514     deref();
2515 }
2516
2517 void Frame::lifeSupportTimerFired(Timer<Frame>*)
2518 {
2519 #ifndef NDEBUG
2520     lifeSupportSet.remove(this);
2521 #endif
2522     deref();
2523 }
2524
2525 // Workaround for the fact that it's hard to delete a frame.
2526 // Call this after doing user-triggered selections to make it easy to delete the frame you entirely selected.
2527 // Can't do this implicitly as part of every setSelection call because in some contexts it might not be good
2528 // for the focus to move to another frame. So instead we call it from places where we are selecting with the
2529 // mouse or the keyboard after setting the selection.
2530 void Frame::selectFrameElementInParentIfFullySelected()
2531 {
2532     // Find the parent frame; if there is none, then we have nothing to do.
2533     Frame *parent = tree()->parent();
2534     if (!parent)
2535         return;
2536     FrameView *parentView = parent->view();
2537     if (!parentView)
2538         return;
2539
2540     // Check if the selection contains the entire frame contents; if not, then there is nothing to do.
2541     if (!d->m_selection.isRange())
2542         return;
2543     if (!isStartOfDocument(VisiblePosition(d->m_selection.start(), d->m_selection.affinity())))
2544         return;
2545     if (!isEndOfDocument(VisiblePosition(d->m_selection.end(), d->m_selection.affinity())))
2546         return;
2547
2548     // Get to the <iframe> or <frame> (or even <object>) element in the parent frame.
2549     Document *doc = document();
2550     if (!doc)
2551         return;
2552     Element *ownerElement = doc->ownerElement();
2553     if (!ownerElement)
2554         return;
2555     Node *ownerElementParent = ownerElement->parentNode();
2556     if (!ownerElementParent)
2557         return;
2558         
2559     // 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.
2560     if (!ownerElementParent->isContentEditable())
2561         return;
2562
2563     // Create compute positions before and after the element.
2564     unsigned ownerElementNodeIndex = ownerElement->nodeIndex();
2565     VisiblePosition beforeOwnerElement(VisiblePosition(ownerElementParent, ownerElementNodeIndex, SEL_DEFAULT_AFFINITY));
2566     VisiblePosition afterOwnerElement(VisiblePosition(ownerElementParent, ownerElementNodeIndex + 1, VP_UPSTREAM_IF_POSSIBLE));
2567
2568     // Focus on the parent frame, and then select from before this element to after.
2569     if (parent->shouldChangeSelection(SelectionController(beforeOwnerElement, afterOwnerElement))) {
2570         parentView->setFocus();
2571         parent->setSelection(SelectionController(beforeOwnerElement, afterOwnerElement));
2572     }
2573 }
2574
2575 void Frame::handleFallbackContent()
2576 {
2577     Element* owner = ownerElement();
2578     if (!owner || !owner->hasTagName(objectTag))
2579         return;
2580     static_cast<HTMLObjectElement*>(owner)->renderFallbackContent();
2581 }
2582
2583 void Frame::setSettings(Settings *settings)
2584 {
2585     d->m_settings = settings;
2586 }
2587
2588 void Frame::provisionalLoadStarted()
2589 {
2590     // we don't want to wait until we get an actual http response back
2591     // to cancel pending redirects, otherwise they might fire before
2592     // that happens.
2593     cancelRedirection(true);
2594 }
2595
2596 bool Frame::userGestureHint()
2597 {
2598     Frame *rootFrame = this;
2599     while (rootFrame->tree()->parent())
2600         rootFrame = rootFrame->tree()->parent();
2601
2602     if (rootFrame->jScript())
2603         return rootFrame->jScript()->interpreter()->wasRunByUserGesture();
2604
2605     return true; // If JavaScript is disabled, a user gesture must have initiated the navigation
2606 }
2607
2608 RenderObject *Frame::renderer() const
2609 {
2610     Document *doc = document();
2611     return doc ? doc->renderer() : 0;
2612 }
2613
2614 Element* Frame::ownerElement()
2615 {
2616     return d->m_ownerElement;
2617 }
2618
2619 RenderPart* Frame::ownerRenderer()
2620 {
2621     Element* ownerElement = d->m_ownerElement;
2622     if (!ownerElement)
2623         return 0;
2624     return static_cast<RenderPart*>(ownerElement->renderer());
2625 }
2626
2627 IntRect Frame::selectionRect() const
2628 {
2629     RenderView *root = static_cast<RenderView*>(renderer());
2630     if (!root)
2631         return IntRect();
2632
2633     return root->selectionRect();
2634 }
2635
2636 // returns FloatRect because going through IntRect would truncate any floats
2637 FloatRect Frame::visibleSelectionRect() const
2638 {
2639     if (!d->m_view)
2640         return FloatRect();
2641     
2642     return intersection(selectionRect(), d->m_view->visibleContentRect());
2643 }
2644
2645 bool Frame::isFrameSet() const
2646 {
2647     Document* document = d->m_doc.get();
2648     if (!document || !document->isHTMLDocument())
2649         return false;
2650     Node *body = static_cast<HTMLDocument*>(document)->body();
2651     return body && body->renderer() && body->hasTagName(framesetTag);
2652 }
2653
2654 bool Frame::openURL(const KURL& URL)
2655 {
2656     ASSERT_NOT_REACHED();
2657     return true;
2658 }
2659
2660 void Frame::didNotOpenURL(const KURL& URL)
2661 {
2662     if (d->m_submittedFormURL == URL)
2663         d->m_submittedFormURL = KURL();
2664 }
2665
2666 // Scans logically forward from "start", including any child frames
2667 static HTMLFormElement *scanForForm(Node *start)
2668 {
2669     Node *n;
2670     for (n = start; n; n = n->traverseNextNode()) {
2671         if (n->hasTagName(formTag))
2672             return static_cast<HTMLFormElement*>(n);
2673         else if (n->isHTMLElement() && static_cast<HTMLElement*>(n)->isGenericFormElement())
2674             return static_cast<HTMLGenericFormElement*>(n)->form();
2675         else if (n->hasTagName(frameTag) || n->hasTagName(iframeTag)) {
2676             Node *childDoc = static_cast<HTMLFrameElement*>(n)->contentDocument();
2677             if (HTMLFormElement *frameResult = scanForForm(childDoc))
2678                 return frameResult;
2679         }
2680     }
2681     return 0;
2682 }
2683
2684 // We look for either the form containing the current focus, or for one immediately after it
2685 HTMLFormElement *Frame::currentForm() const
2686 {
2687     // start looking either at the active (first responder) node, or where the selection is
2688     Node *start = d->m_doc ? d->m_doc->focusNode() : 0;
2689     if (!start)
2690         start = selection().start().node();
2691     
2692     // try walking up the node tree to find a form element
2693     Node *n;
2694     for (n = start; n; n = n->parentNode()) {
2695         if (n->hasTagName(formTag))
2696             return static_cast<HTMLFormElement*>(n);
2697         else if (n->isHTMLElement()
2698                    && static_cast<HTMLElement*>(n)->isGenericFormElement())
2699             return static_cast<HTMLGenericFormElement*>(n)->form();
2700     }
2701     
2702     // try walking forward in the node tree to find a form element
2703     return start ? scanForForm(start) : 0;
2704 }
2705
2706 void Frame::setEncoding(const DeprecatedString& name, bool userChosen)
2707 {
2708     if (!d->m_workingURL.isEmpty())
2709         receivedFirstData();
2710     d->m_encoding = name;
2711     d->m_haveEncoding = userChosen;
2712 }
2713
2714 void Frame::addData(const char *bytes, int length)
2715 {
2716     ASSERT(d->m_workingURL.isEmpty());
2717     ASSERT(d->m_doc);
2718     ASSERT(d->m_doc->parsing());
2719     write(bytes, length);
2720 }
2721
2722 // FIXME: should this go in SelectionController?
2723 void Frame::revealSelection()
2724 {
2725     IntRect rect;
2726     
2727     switch (selection().state()) {
2728         case Selection::NONE:
2729             return;
2730             
2731         case Selection::CARET:
2732             rect = selection().caretRect();
2733             break;
2734             
2735         case Selection::RANGE:
2736             rect = selectionRect();
2737             break;
2738     }
2739     
2740     Position start = selection().start();
2741     Position end = selection().end();
2742     ASSERT(start.node());
2743     if (start.node() && start.node()->renderer()) {
2744         RenderLayer *layer = start.node()->renderer()->enclosingLayer();
2745         if (layer) {
2746             ASSERT(!end.node() || !end.node()->renderer() 
2747                    || (end.node()->renderer()->enclosingLayer() == layer));
2748             layer->scrollRectToVisible(rect);
2749         }
2750     }
2751 }
2752
2753 // FIXME: should this be here?
2754 bool Frame::scrollOverflow(ScrollDirection direction, ScrollGranularity granularity)
2755 {
2756     if (!document()) {
2757         return false;
2758     }
2759     
2760     Node *node = document()->focusNode();
2761     if (node == 0) {
2762         node = d->m_mousePressNode.get();
2763     }
2764     
2765     if (node != 0) {
2766         RenderObject *r = node->renderer();
2767         if (r != 0) {
2768             return r->scroll(direction, granularity);
2769         }
2770     }
2771     
2772     return false;
2773 }
2774
2775 void Frame::handleAutoscroll(RenderLayer* layer)
2776 {
2777     if (d->m_autoscrollTimer.isActive())
2778         return;
2779     d->m_autoscrollLayer = layer;
2780     startAutoscrollTimer();
2781 }
2782
2783 void Frame::autoscrollTimerFired(Timer<Frame>*)
2784 {
2785     if (!d->m_bMousePressed){
2786         stopAutoscrollTimer();
2787         return;
2788     }
2789     if (d->m_autoscrollLayer) {
2790         d->m_autoscrollLayer->autoscroll();
2791     } 
2792 }
2793
2794 RenderObject::NodeInfo Frame::nodeInfoAtPoint(const IntPoint& point, bool allowShadowContent)
2795 {
2796     RenderObject::NodeInfo nodeInfo(true, true);
2797     renderer()->layer()->hitTest(nodeInfo, point);
2798
2799     Node *n;
2800     Widget *widget = 0;
2801     IntPoint widgetPoint(point);
2802     
2803     while (true) {
2804         n = nodeInfo.innerNode();
2805         if (!n || !n->renderer() || !n->renderer()->isWidget())
2806             break;
2807         widget = static_cast<RenderWidget*>(n->renderer())->widget();
2808         if (!widget || !widget->isFrameView())
2809             break;
2810         Frame* frame = static_cast<HTMLFrameElement*>(n)->contentFrame();
2811         if (!frame || !frame->renderer())
2812             break;
2813         int absX, absY;
2814         n->renderer()->absolutePosition(absX, absY, true);
2815         FrameView *view = static_cast<FrameView*>(widget);
2816         widgetPoint.setX(widgetPoint.x() - absX + view->contentsX());
2817         widgetPoint.setY(widgetPoint.y() - absY + view->contentsY());
2818
2819         RenderObject::NodeInfo widgetNodeInfo(true, true);
2820         frame->renderer()->layer()->hitTest(widgetNodeInfo, widgetPoint);
2821         nodeInfo = widgetNodeInfo;
2822     }
2823     
2824     if (!allowShadowContent) {
2825         Node* node = nodeInfo.innerNode();
2826         if (node)
2827             node = node->shadowAncestorNode();
2828         nodeInfo.setInnerNode(node);
2829         node = nodeInfo.innerNonSharedNode();
2830         if (node)
2831             node = node->shadowAncestorNode();
2832         nodeInfo.setInnerNonSharedNode(node); 
2833     }
2834     return nodeInfo;
2835 }
2836
2837 bool Frame::hasSelection()
2838 {
2839     if (selection().isNone())
2840         return false;
2841
2842     // If a part has a selection, it should also have a document.        
2843     ASSERT(document());
2844
2845     return true;
2846 }
2847
2848 void Frame::startAutoscrollTimer()
2849 {
2850     d->m_autoscrollTimer.startRepeating(autoscrollInterval);
2851 }
2852
2853 void Frame::stopAutoscrollTimer()
2854 {
2855     d->m_autoscrollLayer = 0;
2856     d->m_autoscrollTimer.stop();
2857 }
2858
2859 // FIXME: why is this here instead of on the FrameView?
2860 void Frame::paint(GraphicsContext* p, const IntRect& rect)
2861 {
2862 #ifndef NDEBUG
2863     bool fillWithRed;
2864     if (!document() || document()->printing())
2865         fillWithRed = false; // Printing, don't fill with red (can't remember why).
2866     else if (document()->ownerElement())
2867         fillWithRed = false; // Subframe, don't fill with red.
2868     else if (view() && view()->isTransparent())
2869         fillWithRed = false; // Transparent, don't fill with red.
2870     else if (d->m_paintRestriction == PaintRestrictionSelectionOnly || d->m_paintRestriction == PaintRestrictionSelectionOnlyWhiteText)
2871         fillWithRed = false; // Selections are transparent, don't fill with red.
2872     else if (d->m_elementToDraw)
2873         fillWithRed = false; // Element images are transparent, don't fill with red.
2874     else
2875         fillWithRed = true;
2876     
2877     if (fillWithRed)
2878         p->fillRect(rect, Color(0xFF, 0, 0));
2879 #endif
2880     
2881     if (renderer()) {
2882         // d->m_elementToDraw is used to draw only one element
2883         RenderObject *eltRenderer = d->m_elementToDraw ? d->m_elementToDraw->renderer() : 0;
2884         if (d->m_paintRestriction == PaintRestrictionNone)
2885             renderer()->document()->invalidateRenderedRectsForMarkersInRect(rect);
2886         renderer()->layer()->paint(p, rect, d->m_paintRestriction, eltRenderer);
2887
2888 #if __APPLE__
2889         // Regions may have changed as a result of the visibility/z-index of element changing.
2890         if (renderer()->document()->dashboardRegionsDirty())
2891             renderer()->view()->frameView()->updateDashboardRegions();
2892 #endif
2893     } else
2894         LOG_ERROR("called Frame::paint with nil renderer");
2895 }
2896
2897 #if __APPLE__
2898
2899 void Frame::adjustPageHeight(float *newBottom, float oldTop, float oldBottom, float bottomLimit)
2900 {
2901     RenderView *root = static_cast<RenderView*>(document()->renderer());
2902     if (root) {
2903         // Use a context with painting disabled.
2904         GraphicsContext context(0);
2905         root->setTruncatedAt((int)floorf(oldBottom));
2906         IntRect dirtyRect(0, (int)floorf(oldTop), root->docWidth(), (int)ceilf(oldBottom - oldTop));
2907         root->layer()->paint(&context, dirtyRect);
2908         *newBottom = root->bestTruncatedAt();
2909         if (*newBottom == 0)
2910             *newBottom = oldBottom;
2911     } else
2912         *newBottom = oldBottom;
2913 }
2914
2915 #endif
2916
2917 PausedTimeouts *Frame::pauseTimeouts()
2918 {
2919 #ifdef SVG_SUPPORT
2920     if (d->m_doc && d->m_doc->svgExtensions())
2921         d->m_doc->accessSVGExtensions()->pauseAnimations();
2922 #endif
2923
2924     if (d->m_doc && d->m_jscript) {
2925         if (Window* w = Window::retrieveWindow(this))
2926             return w->pauseTimeouts();
2927     }
2928     return 0;
2929 }
2930
2931 void Frame::resumeTimeouts(PausedTimeouts* t)
2932 {
2933 #ifdef SVG_SUPPORT
2934     if (d->m_doc && d->m_doc->svgExtensions())
2935         d->m_doc->accessSVGExtensions()->unpauseAnimations();
2936 #endif
2937
2938     if (d->m_doc && d->m_jscript && d->m_bJScriptEnabled) {
2939         if (Window* w = Window::retrieveWindow(this))
2940             w->resumeTimeouts(t);
2941     }
2942 }
2943
2944 bool Frame::canCachePage()
2945 {
2946     // Only save page state if:
2947     // 1.  We're not a frame or frameset.
2948     // 2.  The page has no unload handler.
2949     // 3.  The page has no password fields.
2950     // 4.  The URL for the page is not https.
2951     // 5.  The page has no applets.
2952     if (tree()->childCount() || d->m_plugins.size() ||
2953         tree()->parent() ||
2954         d->m_url.protocol().startsWith("https") || 
2955         (d->m_doc && (d->m_doc->applets()->length() != 0 ||
2956                       d->m_doc->hasWindowEventListener(unloadEvent) ||
2957                       d->m_doc->hasPasswordField()))) {
2958         return false;
2959     }
2960     return true;
2961 }
2962
2963 void Frame::saveWindowProperties(KJS::SavedProperties *windowProperties)
2964 {
2965     Window *window = Window::retrieveWindow(this);
2966     if (window)
2967         window->saveProperties(*windowProperties);
2968 }
2969
2970 void Frame::saveLocationProperties(SavedProperties *locationProperties)
2971 {
2972     Window *window = Window::retrieveWindow(this);
2973     if (window) {
2974         JSLock lock;
2975         Location *location = window->location();
2976         location->saveProperties(*locationProperties);
2977     }
2978 }
2979
2980 void Frame::restoreWindowProperties(SavedProperties *windowProperties)
2981 {
2982     Window *window = Window::retrieveWindow(this);
2983     if (window)
2984         window->restoreProperties(*windowProperties);
2985 }
2986
2987 void Frame::restoreLocationProperties(SavedProperties *locationProperties)
2988 {
2989     Window *window = Window::retrieveWindow(this);
2990     if (window) {
2991         JSLock lock;
2992         Location *location = window->location();
2993         location->restoreProperties(*locationProperties);
2994     }
2995 }
2996
2997 void Frame::saveInterpreterBuiltins(SavedBuiltins& interpreterBuiltins)
2998 {
2999     if (jScript())
3000         jScript()->interpreter()->saveBuiltins(interpreterBuiltins);
3001 }
3002
3003 void Frame::restoreInterpreterBuiltins(const SavedBuiltins& interpreterBuiltins)
3004 {
3005     if (jScript())
3006         jScript()->interpreter()->restoreBuiltins(interpreterBuiltins);
3007 }
3008
3009 Frame *Frame::frameForWidget(const Widget *widget)
3010 {
3011     ASSERT_ARG(widget, widget);
3012     
3013     Node *node = nodeForWidget(widget);
3014     if (node)
3015         return frameForNode(node);
3016     
3017     // Assume all widgets are either form controls, or FrameViews.
3018     ASSERT(widget->isFrameView());
3019     return static_cast<const FrameView*>(widget)->frame();
3020 }
3021
3022 Frame *Frame::frameForNode(Node *node)
3023 {
3024     ASSERT_ARG(node, node);
3025     return node->document()->frame();
3026 }
3027
3028 Node* Frame::nodeForWidget(const Widget* widget)
3029 {
3030     ASSERT_ARG(widget, widget);
3031     WidgetClient* client = widget->client();
3032     if (!client)
3033         return 0;
3034     return client->element(const_cast<Widget*>(widget));
3035 }
3036
3037 void Frame::clearDocumentFocus(Widget *widget)
3038 {
3039     Node *node = nodeForWidget(widget);
3040     ASSERT(node);
3041     node->document()->setFocusNode(0);
3042 }
3043
3044 void Frame::updatePolicyBaseURL()
3045 {
3046     if (tree()->parent() && tree()->parent()->document())
3047         setPolicyBaseURL(tree()->parent()->document()->policyBaseURL());
3048     else
3049         setPolicyBaseURL(d->m_url.url());
3050 }
3051
3052 void Frame::setPolicyBaseURL(const String& s)
3053 {
3054     if (document())
3055         document()->setPolicyBaseURL(s);
3056     for (Frame* child = tree()->firstChild(); child; child = child->tree()->nextSibling())
3057         child->setPolicyBaseURL(s);
3058 }
3059
3060 void Frame::forceLayout()
3061 {
3062     FrameView *v = d->m_view.get();
3063     if (v) {
3064         v->layout(false);
3065         // We cannot unschedule a pending relayout, since the force can be called with
3066         // a tiny rectangle from a drawRect update.  By unscheduling we in effect
3067         // "validate" and stop the necessary full repaint from occurring.  Basically any basic
3068         // append/remove DHTML is broken by this call.  For now, I have removed the optimization
3069         // until we have a better invalidation stategy. -dwh
3070         //v->unscheduleRelayout();
3071     }
3072 }
3073
3074 void Frame::forceLayoutWithPageWidthRange(float minPageWidth, float maxPageWidth)
3075 {
3076     // Dumping externalRepresentation(m_frame->renderer()).ascii() is a good trick to see
3077     // the state of things before and after the layout
3078     RenderView *root = static_cast<RenderView*>(document()->renderer());
3079     if (root) {
3080         // This magic is basically copied from khtmlview::print
3081         int pageW = (int)ceilf(minPageWidth);
3082         root->setWidth(pageW);
3083         root->setNeedsLayoutAndMinMaxRecalc();
3084         forceLayout();
3085         
3086         // If we don't fit in the minimum page width, we'll lay out again. If we don't fit in the
3087         // maximum page width, we will lay out to the maximum page width and clip extra content.
3088         // FIXME: We are assuming a shrink-to-fit printing implementation.  A cropping
3089         // implementation should not do this!
3090         int rightmostPos = root->rightmostPosition();
3091         if (rightmostPos > minPageWidth) {
3092             pageW = min(rightmostPos, (int)ceilf(maxPageWidth));
3093             root->setWidth(pageW);
3094             root->setNeedsLayoutAndMinMaxRecalc();
3095             forceLayout();
3096         }
3097     }
3098 }
3099
3100 void Frame::sendResizeEvent()
3101 {
3102     if (Document* doc = document())
3103         doc->dispatchWindowEvent(EventNames::resizeEvent, false, false);
3104 }
3105
3106 void Frame::sendScrollEvent()
3107 {
3108     FrameView *v = d->m_view.get();
3109     if (v) {
3110         Document *doc = document();
3111         if (!doc)
3112             return;
3113         doc->dispatchHTMLEvent(scrollEvent, true, false);
3114     }
3115 }
3116
3117 bool Frame::scrollbarsVisible()
3118 {
3119     if (!view())
3120         return false;
3121     
3122     if (view()->hScrollBarMode() == ScrollBarAlwaysOff || view()->vScrollBarMode() == ScrollBarAlwaysOff)
3123         return false;
3124     
3125     return true;
3126 }
3127
3128 void Frame::addMetaData(const String& key, const String& value)
3129 {
3130     d->m_metaData.set(key, value);
3131 }
3132
3133 // This does the same kind of work that Frame::openURL does, except it relies on the fact
3134 // that a higher level already checked that the URLs match and the scrolling is the right thing to do.
3135 void Frame::scrollToAnchor(const KURL& URL)
3136 {
3137     d->m_url = URL;
3138     started();
3139     
3140     gotoAnchor();
3141     
3142     // It's important to model this as a load that starts and immediately finishes.
3143     // Otherwise, the parent frame may think we never finished loading.
3144     d->m_bComplete = false;
3145     checkCompleted();
3146 }
3147
3148 bool Frame::closeURL()
3149 {
3150     saveDocumentState();
3151     stopLoading(true);
3152     clearUndoRedoOperations();
3153     return true;
3154 }
3155
3156 bool Frame::canMouseDownStartSelect(Node* node)
3157 {
3158     if (!node || !node->renderer())
3159         return true;
3160     
3161     // Check to see if -webkit-user-select has been set to none
3162     if (!node->renderer()->canSelect())
3163         return false;
3164     
3165     // Some controls and images can't start a select on a mouse down.
3166     for (RenderObject* curr = node->renderer(); curr; curr = curr->parent()) {
3167         if (curr->style()->userSelect() == SELECT_IGNORE)
3168             return false;
3169     }
3170     
3171     return true;
3172 }
3173
3174 void Frame::handleMouseReleaseDoubleClickEvent(const MouseEventWithHitTestResults& event)
3175 {
3176     passWidgetMouseDownEventToWidget(event, true);
3177 }
3178
3179 bool Frame::passWidgetMouseDownEventToWidget(const MouseEventWithHitTestResults& event, bool isDoubleClick)
3180 {
3181     // Figure out which view to send the event to.
3182     RenderObject *target = event.targetNode() ? event.targetNode()->renderer() : 0;
3183     if (!target)
3184         return false;
3185     
3186     Widget* widget = RenderLayer::gScrollBar;
3187     if (!widget) {
3188         if (!target->isWidget())
3189             return false;
3190         widget = static_cast<RenderWidget*>(target)->widget();
3191     }
3192     
3193     // Doubleclick events don't exist in Cocoa.  Since passWidgetMouseDownEventToWidget will
3194     // just pass _currentEvent down to the widget,  we don't want to call it for events that
3195     // don't correspond to Cocoa events.  The mousedown/ups will have already been passed on as
3196     // part of the pressed/released handling.
3197     if (!isDoubleClick)
3198         return passMouseDownEventToWidget(widget);
3199     return true;
3200 }
3201
3202 bool Frame::passWidgetMouseDownEventToWidget(RenderWidget *renderWidget)
3203 {
3204     return passMouseDownEventToWidget(renderWidget->widget());
3205 }
3206
3207 void Frame::clearTimers(FrameView *view)
3208 {
3209     if (view) {
3210         view->unscheduleRelayout();
3211         if (view->frame()) {
3212             Document* document = view->frame()->document();
3213             if (document && document->renderer() && document->renderer()->layer())
3214                 document->renderer()->layer()->suspendMarquees();
3215         }
3216     }
3217 }
3218
3219 void Frame::clearTimers()
3220 {
3221     clearTimers(d->m_view.get());
3222 }
3223
3224 // FIXME: selection controller?
3225 void Frame::centerSelectionInVisibleArea() const
3226 {
3227     IntRect rect;
3228     
3229     switch (selection().state()) {
3230         case Selection::NONE:
3231             return;
3232             
3233         case Selection::CARET:
3234             rect = selection().caretRect();
3235             break;
3236             
3237         case Selection::RANGE:
3238             rect = selectionRect();
3239             break;
3240     }
3241     
3242     Position start = selection().start();
3243     Position end = selection().end();
3244     ASSERT(start.node());
3245     if (start.node() && start.node()->renderer()) {
3246         RenderLayer *layer = start.node()->renderer()->enclosingLayer();
3247         if (layer) {
3248             ASSERT(!end.node() || !end.node()->renderer() 
3249                    || (end.node()->renderer()->enclosingLayer() == layer));
3250             layer->scrollRectToVisible(rect, RenderLayer::gAlignCenterAlways, RenderLayer::gAlignCenterAlways);
3251         }
3252     }
3253 }
3254
3255 RenderStyle *Frame::styleForSelectionStart(Node *&nodeToRemove) const
3256 {
3257     nodeToRemove = 0;
3258     
3259     if (!document())
3260         return 0;
3261     if (d->m_selection.isNone())
3262         return 0;
3263     
3264     Position pos = VisiblePosition(d->m_selection.start(), d->m_selection.affinity()).deepEquivalent();
3265     if (!pos.inRenderedContent())
3266         return 0;
3267     Node *node = pos.node();
3268     if (!node)
3269         return 0;
3270     
3271     if (!d->m_typingStyle)
3272         return node->renderer()->style();
3273     
3274     ExceptionCode ec = 0;
3275     RefPtr<Element> styleElement = document()->createElementNS(xhtmlNamespaceURI, "span", ec);
3276     ASSERT(ec == 0);
3277     
3278     styleElement->setAttribute(styleAttr, d->m_typingStyle->cssText().impl(), ec);
3279     ASSERT(ec == 0);
3280     
3281     styleElement->appendChild(document()->createEditingTextNode(""), ec);
3282     ASSERT(ec == 0);
3283     
3284     node->parentNode()->appendChild(styleElement, ec);
3285     ASSERT(ec == 0);
3286     
3287     nodeToRemove = styleElement.get();    
3288     return styleElement->renderer()->style();
3289 }
3290
3291 void Frame::setMediaType(const String& type)
3292 {
3293     if (d->m_view)
3294         d->m_view->setMediaType(type);
3295 }
3296
3297 void Frame::setSelectionFromNone()
3298 {
3299     // Put a caret inside the body if the entire frame is editable (either the 
3300     // entire WebView is editable or designMode is on for this document).
3301     Document *doc = document();
3302     if (!doc || !selection().isNone() || !isContentEditable())
3303         return;
3304         
3305     Node* node = doc->documentElement();
3306     while (node && !node->hasTagName(bodyTag))
3307         node = node->traverseNextNode();
3308     if (node)
3309         setSelection(SelectionController(Position(node, 0), DOWNSTREAM));
3310 }
3311
3312 bool Frame::isActive() const
3313 {
3314     return d->m_isActive;
3315 }
3316
3317 void Frame::setIsActive(bool flag)
3318 {
3319     if (d->m_isActive == flag)
3320         return;
3321     
3322     d->m_isActive = flag;
3323
3324     // This method does the job of updating the view based on whether the view is "active".
3325     // This involves three kinds of drawing updates:
3326
3327     // 1. The background color used to draw behind selected content (active | inactive color)
3328     if (d->m_view)
3329         d->m_view->updateContents(enclosingIntRect(visibleSelectionRect()));
3330
3331     // 2. Caret blinking (blinks | does not blink)
3332     if (flag)
3333         setSelectionFromNone();
3334     setCaretVisible(flag);
3335     
3336     // 3. The drawing of a focus ring around links in web pages.
3337     Document *doc = document();
3338     if (doc) {
3339         Node *node = doc->focusNode();
3340         if (node) {
3341             node->setChanged();
3342             if (node->renderer() && node->renderer()->style()->hasAppearance())
3343                 theme()->stateChanged(node->renderer(), FocusState);
3344         }
3345     }
3346     
3347     // 4, Changing the tint of controls from clear to aqua/graphite and vice versa.  We
3348     // do a "fake" paint.  When the theme gets a paint call, it can then do an invalidate.  This is only
3349     // done if the theme supports control tinting.
3350     if (doc && d->m_view && theme()->supportsControlTints() && renderer()) {
3351         doc->updateLayout(); // Ensure layout is up to date.
3352         IntRect visibleRect(enclosingIntRect(d->m_view->visibleContentRect()));
3353         GraphicsContext context((PlatformGraphicsContext*)0);
3354         context.setUpdatingControlTints(true);
3355         paint(&context, visibleRect);
3356     }
3357 }
3358
3359 void Frame::setWindowHasFocus(bool flag)
3360 {
3361     if (d->m_windowHasFocus == flag)
3362         return;
3363     d->m_windowHasFocus = flag;
3364     
3365     if (Document *doc = document())
3366         doc->dispatchWindowEvent(flag ? focusEvent : blurEvent, false, false);
3367 }
3368
3369 bool Frame::inViewSourceMode() const
3370 {
3371     return d->m_inViewSourceMode;
3372 }
3373
3374 void Frame::setInViewSourceMode(bool mode) const
3375 {
3376     d->m_inViewSourceMode = mode;
3377 }
3378   
3379 UChar Frame::backslashAsCurrencySymbol() const
3380 {
3381     Document *doc = document();
3382     if (!doc)
3383         return '\\';
3384     Decoder *decoder = doc->decoder();
3385     if (!decoder)
3386         return '\\';
3387
3388     return decoder->encoding().backslashAsCurrencySymbol();
3389 }
3390
3391 bool Frame::markedTextUsesUnderlines() const
3392 {
3393     return d->m_markedTextUsesUnderlines;
3394 }
3395
3396 DeprecatedValueList<MarkedTextUnderline> Frame::markedTextUnderlines() const
3397 {
3398     return d->m_markedTextUnderlines;
3399 }
3400
3401 // Searches from the beginning of the document if nothing is selected.
3402 bool Frame::findString(const String& target, bool forward, bool caseFlag, bool wrapFlag)
3403 {
3404     if (target.isEmpty())
3405         return false;
3406     
3407     // Initially search from the start (if forward) or end (if backward) of the selection, and search to edge of document.
3408     RefPtr<Range> searchRange(rangeOfContents(document()));
3409     if (selection().start().node()) {
3410         if (forward)
3411             setStart(searchRange.get(), VisiblePosition(selection().start(), selection().affinity()));
3412         else
3413             setEnd(searchRange.get(), VisiblePosition(selection().end(), selection().affinity()));
3414     }
3415     RefPtr<Range> resultRange(findPlainText(searchRange.get(), target, forward, caseFlag));
3416     Selection sel = selection().selection();
3417     // If the found range is already selected, find again.
3418     // Build a selection with the found range to remove collapsed whitespace.
3419     // Compare ranges instead of selection objects to ignore the way that the current selection was made.
3420     if (!sel.isNone() && *Selection(resultRange.get()).toRange() == *sel.toRange()) {
3421         searchRange = rangeOfContents(document());
3422         if (forward)
3423             setStart(searchRange.get(), VisiblePosition(sel.end(), sel.affinity()));
3424         else
3425             setEnd(searchRange.get(), VisiblePosition(sel.start(), sel.affinity()));
3426         resultRange = findPlainText(searchRange.get(), target, forward, caseFlag);
3427     }
3428     
3429     int exception = 0;
3430     
3431     // If we didn't find anything and we're wrapping, search again in the entire document (this will
3432     // redundantly re-search the area already searched in some cases).
3433     if (resultRange->collapsed(exception) && wrapFlag) {
3434         searchRange = rangeOfContents(document());
3435         resultRange = findPlainText(searchRange.get(), target, forward, caseFlag);
3436         // We used to return false here if we ended up with the same range that we started with
3437         // (e.g., the selection was already the only instance of this text). But we decided that
3438         // this should be a success case instead, so we'll just fall through in that case.
3439     }
3440
3441     if (resultRange->collapsed(exception))
3442         return false;
3443
3444     setSelection(SelectionController(resultRange.get(), DOWNSTREAM));
3445     revealSelection();
3446     return true;
3447 }
3448
3449 unsigned Frame::markAllMatchesForText(const String& target, bool caseFlag)
3450 {
3451     if (target.isEmpty())
3452         return 0;
3453     
3454     RefPtr<Range> searchRange(rangeOfContents(document()));
3455     
3456     int exception = 0;
3457     unsigned matchCount = 0;
3458     do {
3459         RefPtr<Range> resultRange(findPlainText(searchRange.get(), target, true, caseFlag));
3460         if (resultRange->collapsed(exception))
3461             break;
3462         
3463         // A non-collapsed result range can in some funky whitespace cases still not
3464         // advance the range's start position (4509328). Break to avoid infinite loop.
3465         VisiblePosition newStart = endVisiblePosition(resultRange.get(), DOWNSTREAM);
3466         if (newStart == startVisiblePosition(searchRange.get(), DOWNSTREAM))
3467             break;
3468
3469         ++matchCount;
3470         document()->addMarker(resultRange.get(), DocumentMarker::TextMatch);        
3471         
3472         setStart(searchRange.get(), newStart);
3473     } while (true);
3474     
3475     // Do a "fake" paint in order to execute the code that computes the rendered rect for 
3476     // each text match.
3477     Document* doc = document();
3478     if (doc && d->m_view && renderer()) {
3479         doc->updateLayout(); // Ensure layout is up to date.
3480         IntRect visibleRect(enclosingIntRect(d->m_view->visibleContentRect()));
3481         GraphicsContext context((PlatformGraphicsContext*)0);
3482         context.setPaintingDisabled(true);
3483         paint(&context, visibleRect);
3484     }
3485     
3486     return matchCount;
3487 }
3488
3489 bool Frame::markedTextMatchesAreHighlighted() const
3490 {
3491     return d->m_highlightTextMatches;
3492 }
3493
3494 void Frame::setMarkedTextMatchesAreHighlighted(bool flag)
3495 {
3496     if (flag == d->m_highlightTextMatches)
3497         return;
3498     
3499     d->m_highlightTextMatches = flag;
3500     document()->repaintMarkers(DocumentMarker::TextMatch);
3501 }
3502
3503 void Frame::prepareForUserAction()
3504 {
3505     // Reset the multiple form submission protection code.
3506     // We'll let you submit the same form twice if you do two separate user actions.
3507     d->m_submittedFormURL = KURL();
3508 }
3509
3510 Node *Frame::mousePressNode()
3511 {
3512     return d->m_mousePressNode.get();
3513 }
3514
3515 bool Frame::isComplete() const
3516 {
3517     return d->m_bComplete;
3518 }
3519
3520 bool Frame::isLoadingMainResource() const
3521 {
3522     return d->m_bLoadingMainResource;
3523 }
3524
3525 FrameTree* Frame::tree() const
3526 {
3527     return &d->m_treeNode;
3528 }
3529
3530 DOMWindow* Frame::domWindow() const
3531 {
3532     if (!d->m_domWindow)
3533         d->m_domWindow = new DOMWindow(const_cast<Frame*>(this));
3534
3535     return d->m_domWindow.get();
3536 }
3537
3538 KURL Frame::url() const
3539 {
3540     return d->m_url;
3541 }
3542
3543 void Frame::startRedirectionTimer()
3544 {
3545     d->m_redirectionTimer.startOneShot(d->m_delayRedirect);
3546 }
3547
3548 void Frame::stopRedirectionTimer()
3549 {
3550     d->m_redirectionTimer.stop();
3551 }
3552
3553 void Frame::frameDetached()
3554 {
3555 }
3556
3557 void Frame::updateBaseURLForEmptyDocument()
3558 {
3559     Element* owner = ownerElement();
3560     // FIXME: Should embed be included?
3561     if (owner && (owner->hasTagName(iframeTag) || owner->hasTagName(objectTag) || owner->hasTagName(embedTag)))
3562         d->m_doc->setBaseURL(tree()->parent()->d->m_doc->baseURL());
3563 }
3564
3565 Page* Frame::page() const
3566 {
3567     return d->m_page;
3568 }
3569
3570 void Frame::pageDestroyed()
3571 {
3572     d->m_page = 0;
3573
3574     // This will stop any JS timers
3575     if (d->m_jscript && d->m_jscript->haveInterpreter())
3576         if (Window* w = Window::retrieveWindow(this))
3577             w->disconnectFrame();
3578 }
3579
3580 void Frame::completed(bool complete)
3581 {
3582     ref();
3583     for (Frame* child = tree()->firstChild(); child; child = child->tree()->nextSibling())
3584         child->parentCompleted();
3585     if (Frame* parent = tree()->parent())
3586         parent->childCompleted(complete);
3587     submitFormAgain();
3588     deref();
3589 }
3590
3591 void Frame::setStatusBarText(const String&)
3592 {
3593 }
3594
3595 void Frame::started()
3596 {
3597     for (Frame* frame = this; frame; frame = frame->tree()->parent())
3598         frame->d->m_bComplete = false;
3599 }
3600
3601 void Frame::disconnectOwnerElement()
3602 {
3603     if (d->m_ownerElement)
3604         d->m_page->decrementFrameCount();
3605         
3606     d->m_ownerElement = 0;
3607 }
3608
3609 String Frame::documentTypeString() const
3610 {
3611     if (Document *doc = document())
3612         if (DocumentType *doctype = doc->realDocType())
3613             return doctype->toString();
3614
3615     return String();
3616 }
3617
3618 bool Frame::containsPlugins() const 
3619
3620     return d->m_plugins.size() != 0;
3621 }
3622
3623 bool Frame::prohibitsScrolling() const
3624 {
3625     return d->m_prohibitsScrolling;
3626 }
3627
3628 void Frame::setProhibitsScrolling(const bool prohibit)
3629 {
3630     d->m_prohibitsScrolling = prohibit;
3631 }
3632
3633 } // namespace WebCore