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