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