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