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