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