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