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