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