28ab0a08aa4049be9b5f9eddac0ea227a72aeb55
[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 TextGranularity Frame::selectionGranularity() const
1237 {
1238     return d->m_selectionGranularity;
1239 }
1240
1241 void Frame::setSelectionGranularity(TextGranularity granularity) const
1242 {
1243     d->m_selectionGranularity = granularity;
1244 }
1245
1246 SelectionController* Frame::dragCaretController() const
1247 {
1248     return d->m_page->dragCaretController();
1249 }
1250
1251 const Selection& Frame::mark() const
1252 {
1253     return d->m_mark;
1254 }
1255
1256 void Frame::setMark(const Selection& s)
1257 {
1258     ASSERT(!s.base().node() || s.base().node()->document() == document());
1259     ASSERT(!s.extent().node() || s.extent().node()->document() == document());
1260     ASSERT(!s.start().node() || s.start().node()->document() == document());
1261     ASSERT(!s.end().node() || s.end().node()->document() == document());
1262
1263     d->m_mark = s;
1264 }
1265
1266 void Frame::notifyRendererOfSelectionChange(bool userTriggered)
1267 {
1268     RenderObject* renderer = 0;
1269     if (selectionController()->rootEditableElement())
1270         renderer = selectionController()->rootEditableElement()->shadowAncestorNode()->renderer();
1271
1272     // If the current selection is in a textfield or textarea, notify the renderer that the selection has changed
1273     if (renderer && (renderer->isTextArea() || renderer->isTextField()))
1274         static_cast<RenderTextControl*>(renderer)->selectionChanged(userTriggered);
1275 }
1276
1277 void Frame::invalidateSelection()
1278 {
1279     clearCaretRectIfNeeded();
1280     selectionController()->setNeedsLayout();
1281     selectionLayoutChanged();
1282 }
1283
1284 void Frame::setCaretVisible(bool flag)
1285 {
1286     if (d->m_caretVisible == flag)
1287         return;
1288     clearCaretRectIfNeeded();
1289     if (flag)
1290         setFocusNodeIfNeeded();
1291     d->m_caretVisible = flag;
1292     selectionLayoutChanged();
1293 }
1294
1295
1296 void Frame::clearCaretRectIfNeeded()
1297 {
1298     if (d->m_caretPaint) {
1299         d->m_caretPaint = false;
1300         selectionController()->needsCaretRepaint();
1301     }        
1302 }
1303
1304 // Helper function that tells whether a particular node is an element that has an entire
1305 // Frame and FrameView, a <frame>, <iframe>, or <object>.
1306 static bool isFrameElement(const Node *n)
1307 {
1308     if (!n)
1309         return false;
1310     RenderObject *renderer = n->renderer();
1311     if (!renderer || !renderer->isWidget())
1312         return false;
1313     Widget* widget = static_cast<RenderWidget*>(renderer)->widget();
1314     return widget && widget->isFrameView();
1315 }
1316
1317 void Frame::setFocusNodeIfNeeded()
1318 {
1319     if (!document() || selectionController()->isNone() || !d->m_isActive)
1320         return;
1321
1322     Node* target = selectionController()->rootEditableElement();
1323     if (target) {
1324         RenderObject* renderer = target->renderer();
1325
1326         // Walk up the render tree to search for a node to focus.
1327         // Walking up the DOM tree wouldn't work for shadow trees, like those behind the engine-based text fields.
1328         while (renderer) {
1329             // We don't want to set focus on a subframe when selecting in a parent frame,
1330             // so add the !isFrameElement check here. There's probably a better way to make this
1331             // work in the long term, but this is the safest fix at this time.
1332             if (target && target->isMouseFocusable() && !isFrameElement(target)) {
1333                 document()->setFocusNode(target);
1334                 return;
1335             }
1336             renderer = renderer->parent();
1337             if (renderer)
1338                 target = renderer->element();
1339         }
1340         document()->setFocusNode(0);
1341     }
1342 }
1343
1344 void Frame::selectionLayoutChanged()
1345 {
1346     // kill any caret blink timer now running
1347     d->m_caretBlinkTimer.stop();
1348
1349     // see if a new caret blink timer needs to be started
1350     if (d->m_caretVisible && d->m_caretBlinks && 
1351         selectionController()->isCaret() && selectionController()->start().node()->isContentEditable()) {
1352         d->m_caretBlinkTimer.startRepeating(caretBlinkFrequency);
1353         d->m_caretPaint = true;
1354         selectionController()->needsCaretRepaint();
1355     }
1356
1357     if (d->m_doc)
1358         d->m_doc->updateSelection();
1359 }
1360
1361 void Frame::setXPosForVerticalArrowNavigation(int x)
1362 {
1363     d->m_xPosForVerticalArrowNavigation = x;
1364 }
1365
1366 int Frame::xPosForVerticalArrowNavigation() const
1367 {
1368     return d->m_xPosForVerticalArrowNavigation;
1369 }
1370
1371 void Frame::caretBlinkTimerFired(Timer<Frame>*)
1372 {
1373     // Might be better to turn the timer off during some of these circumstances
1374     // and assert rather then letting the timer fire and do nothing here.
1375     // Could do that in selectionLayoutChanged.
1376
1377     if (!d->m_caretVisible)
1378         return;
1379     if (!d->m_caretBlinks)
1380         return;
1381     if (!selectionController()->isCaret())
1382         return;
1383     bool caretPaint = d->m_caretPaint;
1384     if (d->m_bMousePressed && caretPaint)
1385         return;
1386     d->m_caretPaint = !caretPaint;
1387     selectionController()->needsCaretRepaint();
1388 }
1389
1390 void Frame::paintCaret(GraphicsContext* p, const IntRect& rect) const
1391 {
1392     if (d->m_caretPaint)
1393         selectionController()->paintCaret(p, rect);
1394 }
1395
1396 void Frame::paintDragCaret(GraphicsContext* p, const IntRect& rect) const
1397 {
1398     SelectionController* dragCaretController = d->m_page->dragCaretController();
1399     assert(dragCaretController->selection().isCaret());
1400     if (dragCaretController->selection().start().node()->document()->frame() == this)
1401         dragCaretController->paintCaret(p, rect);
1402 }
1403
1404 void Frame::urlSelected(const DeprecatedString& url, const String& target)
1405 {
1406     urlSelected(ResourceRequest(completeURL(url)), target);
1407 }
1408
1409 void Frame::urlSelected(const ResourceRequest& request, const String& _target)
1410 {
1411   String target = _target;
1412   if (target.isEmpty() && d->m_doc)
1413     target = d->m_doc->baseTarget();
1414
1415   const KURL& url = request.url();
1416
1417   if (url.url().startsWith("javascript:", false)) {
1418     executeScript(0, KURL::decode_string(url.url().mid(11)), true);
1419     return;
1420   }
1421
1422   if (!url.isValid())
1423     // ### ERROR HANDLING
1424     return;
1425
1426   ResourceRequest requestCopy = request;
1427   requestCopy.frameName = target;
1428
1429   if (d->m_bHTTPRefresh)
1430     d->m_bHTTPRefresh = false;
1431
1432   if (!d->m_referrer.isEmpty())
1433     requestCopy.setReferrer(d->m_referrer);
1434
1435   urlSelected(requestCopy);
1436 }
1437
1438 bool Frame::requestFrame(Element* ownerElement, const String& urlParam, const AtomicString& frameName)
1439 {
1440     DeprecatedString _url = urlParam.deprecatedString();
1441     // Support for <frame src="javascript:string">
1442     KURL scriptURL;
1443     KURL url;
1444     if (_url.startsWith("javascript:", false)) {
1445         scriptURL = _url;
1446         url = "about:blank";
1447     } else
1448         url = completeURL(_url);
1449
1450     Frame* frame = tree()->child(frameName);
1451     if (frame) {
1452         ResourceRequest request(url);
1453         request.setReferrer(d->m_referrer);
1454         request.reload = (d->m_cachePolicy == CachePolicyReload) || (d->m_cachePolicy == CachePolicyRefresh);
1455         frame->openURLRequest(request);
1456     } else
1457         frame = loadSubframe(ownerElement, url, frameName, d->m_referrer);
1458     
1459     if (!frame)
1460         return false;
1461
1462     if (!scriptURL.isEmpty())
1463         frame->replaceContentsWithScriptResult(scriptURL);
1464
1465     return true;
1466 }
1467
1468 bool Frame::requestObject(RenderPart* renderer, const String& url, const AtomicString& frameName,
1469                           const String& mimeType, const Vector<String>& paramNames, const Vector<String>& paramValues)
1470 {
1471     KURL completedURL;
1472     if (!url.isEmpty())
1473         completedURL = completeURL(url.deprecatedString());
1474     
1475     if (url.isEmpty() && mimeType.isEmpty())
1476         return true;
1477     
1478     bool useFallback;
1479     if (shouldUsePlugin(renderer->element(), completedURL, mimeType, renderer->hasFallbackContent(), useFallback))
1480         return loadPlugin(renderer, completedURL, mimeType, paramNames, paramValues, useFallback);
1481
1482     ASSERT(renderer->node()->hasTagName(objectTag) || renderer->node()->hasTagName(embedTag));
1483     AtomicString uniqueFrameName = tree()->uniqueChildName(frameName);
1484     static_cast<HTMLPlugInElement*>(renderer->node())->setFrameName(uniqueFrameName);
1485     
1486     // FIXME: ok to always make a new one? when does the old frame get removed?
1487     return loadSubframe(static_cast<Element*>(renderer->node()), completedURL, uniqueFrameName, d->m_referrer);
1488 }
1489
1490 bool Frame::shouldUsePlugin(Node* element, const KURL& url, const String& mimeType, bool hasFallback, bool& useFallback)
1491 {
1492     useFallback = false;
1493     ObjectContentType objectType = objectContentType(url, mimeType);
1494
1495     // if an object's content can't be handled and it has no fallback, let
1496     // it be handled as a plugin to show the broken plugin icon
1497     if (objectType == ObjectContentNone && hasFallback)
1498         useFallback = true;
1499
1500     return objectType == ObjectContentNone || objectType == ObjectContentPlugin;
1501 }
1502
1503
1504 bool Frame::loadPlugin(RenderPart *renderer, const KURL& url, const String& mimeType, 
1505                        const Vector<String>& paramNames, const Vector<String>& paramValues, bool useFallback)
1506 {
1507     if (useFallback) {
1508         checkEmitLoadEvent();
1509         return false;
1510     }
1511
1512     Element *pluginElement;
1513     if (renderer && renderer->node() && renderer->node()->isElementNode())
1514         pluginElement = static_cast<Element*>(renderer->node());
1515     else
1516         pluginElement = 0;
1517         
1518     Plugin* plugin = createPlugin(pluginElement, url, paramNames, paramValues, mimeType);
1519     if (!plugin) {
1520         checkEmitLoadEvent();
1521         return false;
1522     }
1523     d->m_plugins.append(plugin);
1524     
1525     if (renderer && plugin->view())
1526         renderer->setWidget(plugin->view());
1527     
1528     checkEmitLoadEvent();
1529     
1530     return true;
1531 }
1532
1533 Frame* Frame::loadSubframe(Element* ownerElement, const KURL& url, const String& name, const String& referrer)
1534 {
1535     Frame* frame = createFrame(url, name, ownerElement, referrer);
1536     if (!frame)  {
1537         checkEmitLoadEvent();
1538         return 0;
1539     }
1540     
1541     frame->childBegin();
1542     
1543     if (ownerElement->renderer() && frame->view())
1544         static_cast<RenderWidget*>(ownerElement->renderer())->setWidget(frame->view());
1545     
1546     checkEmitLoadEvent();
1547     
1548     // In these cases, the synchronous load would have finished
1549     // before we could connect the signals, so make sure to send the 
1550     // completed() signal for the child by hand
1551     // FIXME: In this case the Frame will have finished loading before 
1552     // it's being added to the child list. It would be a good idea to
1553     // create the child first, then invoke the loader separately.
1554     if (url.isEmpty() || url == "about:blank") {
1555         frame->completed(false);
1556         frame->checkCompleted();
1557     }
1558
1559     return frame;
1560 }
1561
1562 void Frame::clearRecordedFormValues()
1563 {
1564     d->m_formAboutToBeSubmitted = 0;
1565     d->m_formValuesAboutToBeSubmitted.clear();
1566 }
1567
1568 void Frame::recordFormValue(const String& name, const String& value, PassRefPtr<HTMLFormElement> element)
1569 {
1570     d->m_formAboutToBeSubmitted = element;
1571     d->m_formValuesAboutToBeSubmitted.set(name, value);
1572 }
1573
1574 void Frame::submitFormAgain()
1575 {
1576     FramePrivate::SubmitForm* form = d->m_submitForm;
1577     d->m_submitForm = 0;
1578     if (d->m_doc && !d->m_doc->parsing() && form)
1579         submitForm(form->submitAction, form->submitUrl, form->submitFormData,
1580             form->target, form->submitContentType, form->submitBoundary);
1581     delete form;
1582 }
1583
1584 void Frame::submitForm(const char *action, const String& url, const FormData& formData, const String& _target, const String& contentType, const String& boundary)
1585 {
1586   KURL u = completeURL(url.deprecatedString());
1587
1588   if (!u.isValid())
1589     // ### ERROR HANDLING!
1590     return;
1591
1592   DeprecatedString urlstring = u.url();
1593   if (urlstring.startsWith("javascript:", false)) {
1594     urlstring = KURL::decode_string(urlstring);
1595     d->m_executingJavaScriptFormAction = true;
1596     executeScript(0, urlstring.mid(11));
1597     d->m_executingJavaScriptFormAction = false;
1598     return;
1599   }
1600
1601   ResourceRequest request;
1602
1603   if (!d->m_referrer.isEmpty())
1604      request.setReferrer(d->m_referrer);
1605
1606   request.frameName = _target.isEmpty() ? d->m_doc->baseTarget() : _target ;
1607
1608   // Handle mailto: forms
1609   if (u.protocol() == "mailto") {
1610       // 1)  Check for attach= and strip it
1611       DeprecatedString q = u.query().mid(1);
1612       DeprecatedStringList nvps = DeprecatedStringList::split("&", q);
1613       bool triedToAttach = false;
1614
1615       for (DeprecatedStringList::Iterator nvp = nvps.begin(); nvp != nvps.end(); ++nvp) {
1616          DeprecatedStringList pair = DeprecatedStringList::split("=", *nvp);
1617          if (pair.count() >= 2) {
1618             if (pair.first().lower() == "attach") {
1619                nvp = nvps.remove(nvp);
1620                triedToAttach = true;
1621             }
1622          }
1623       }
1624
1625
1626       // 2)  Append body=
1627       DeprecatedString bodyEnc;
1628       if (contentType.lower() == "multipart/form-data")
1629          // FIXME: is this correct?  I suspect not
1630          bodyEnc = KURL::encode_string(formData.flattenToString().deprecatedString());
1631       else if (contentType.lower() == "text/plain") {
1632          // Convention seems to be to decode, and s/&/\n/
1633          DeprecatedString tmpbody = formData.flattenToString().deprecatedString();
1634          tmpbody.replace('&', '\n');
1635          tmpbody.replace('+', ' ');
1636          tmpbody = KURL::decode_string(tmpbody);  // Decode the rest of it
1637          bodyEnc = KURL::encode_string(tmpbody);  // Recode for the URL
1638       } else
1639          bodyEnc = KURL::encode_string(formData.flattenToString().deprecatedString());
1640
1641       nvps.append(String::sprintf("body=%s", bodyEnc.latin1()).deprecatedString());
1642       q = nvps.join("&");
1643       u.setQuery(q);
1644   } 
1645
1646   if (strcmp(action, "get") == 0) {
1647     if (u.protocol() != "mailto")
1648        u.setQuery(formData.flattenToString().deprecatedString());
1649     request.setDoPost(false);
1650   } else {
1651     request.postData = formData;
1652     request.setDoPost(true);
1653
1654     // construct some user headers if necessary
1655     if (contentType.isNull() || contentType == "application/x-www-form-urlencoded")
1656       request.setContentType("Content-Type: application/x-www-form-urlencoded");
1657     else // contentType must be "multipart/form-data"
1658       request.setContentType("Content-Type: " + contentType + "; boundary=" + boundary);
1659   }
1660
1661   if (d->m_doc->parsing() || d->m_runningScripts > 0) {
1662     if (d->m_submitForm)
1663         return;
1664     d->m_submitForm = new FramePrivate::SubmitForm;
1665     d->m_submitForm->submitAction = action;
1666     d->m_submitForm->submitUrl = url;
1667     d->m_submitForm->submitFormData = formData;
1668     d->m_submitForm->target = _target;
1669     d->m_submitForm->submitContentType = contentType;
1670     d->m_submitForm->submitBoundary = boundary;
1671   } else {
1672       request.setURL(u);
1673       submitForm(request);
1674   }
1675 }
1676
1677 void Frame::parentCompleted()
1678 {
1679     if (d->m_scheduledRedirection != noRedirectionScheduled && !d->m_redirectionTimer.isActive())
1680         startRedirectionTimer();
1681 }
1682
1683 void Frame::childCompleted(bool complete)
1684 {
1685     if (complete && !tree()->parent())
1686         d->m_bPendingChildRedirection = true;
1687     checkCompleted();
1688 }
1689
1690 int Frame::zoomFactor() const
1691 {
1692   return d->m_zoomFactor;
1693 }
1694
1695 void Frame::setZoomFactor(int percent)
1696 {  
1697   if (d->m_zoomFactor == percent)
1698       return;
1699
1700   d->m_zoomFactor = percent;
1701
1702   if (d->m_doc)
1703       d->m_doc->recalcStyle(Node::Force);
1704
1705   for (Frame* child = tree()->firstChild(); child; child = child->tree()->nextSibling())
1706       child->setZoomFactor(d->m_zoomFactor);
1707
1708   if (d->m_doc && d->m_doc->renderer() && d->m_doc->renderer()->needsLayout())
1709       view()->layout();
1710 }
1711
1712 void Frame::setJSStatusBarText(const String& text)
1713 {
1714     d->m_kjsStatusBarText = text;
1715     setStatusBarText(d->m_kjsStatusBarText);
1716 }
1717
1718 void Frame::setJSDefaultStatusBarText(const String& text)
1719 {
1720     d->m_kjsDefaultStatusBarText = text;
1721     setStatusBarText(d->m_kjsDefaultStatusBarText);
1722 }
1723
1724 String Frame::jsStatusBarText() const
1725 {
1726     return d->m_kjsStatusBarText;
1727 }
1728
1729 String Frame::jsDefaultStatusBarText() const
1730 {
1731    return d->m_kjsDefaultStatusBarText;
1732 }
1733
1734 String Frame::referrer() const
1735 {
1736     return d->m_referrer;
1737 }
1738
1739 String Frame::lastModified() const
1740 {
1741     return d->m_lastModified;
1742 }
1743
1744 void Frame::reparseConfiguration()
1745 {
1746     setAutoloadImages(d->m_settings->autoLoadImages());
1747         
1748     d->m_bJScriptEnabled = d->m_settings->isJavaScriptEnabled();
1749     d->m_bJavaEnabled = d->m_settings->isJavaEnabled();
1750     d->m_bPluginsEnabled = d->m_settings->isPluginsEnabled();
1751
1752     const KURL& userStyleSheetLocation = d->m_settings->userStyleSheetLocation();
1753     if (!userStyleSheetLocation.isEmpty())
1754         setUserStyleSheetLocation(userStyleSheetLocation);
1755     else
1756         setUserStyleSheet(String());
1757
1758     // FIXME: It's not entirely clear why the following is needed.
1759     // The document automatically does this as required when you set the style sheet.
1760     // But we had problems when this code was removed. Details are in
1761     // <http://bugzilla.opendarwin.org/show_bug.cgi?id=8079>.
1762     if (d->m_doc)
1763         d->m_doc->updateStyleSelector();
1764 }
1765
1766 bool Frame::shouldDragAutoNode(Node *node, const IntPoint& point) const
1767 {
1768     // No KDE impl yet
1769     return false;
1770 }
1771
1772 bool Frame::isPointInsideSelection(const IntPoint& point)
1773 {
1774     // Treat a collapsed selection like no selection.
1775     if (!selectionController()->isRange())
1776         return false;
1777     if (!document()->renderer()) 
1778         return false;
1779     
1780     RenderObject::NodeInfo nodeInfo(true, true);
1781     document()->renderer()->layer()->hitTest(nodeInfo, point);
1782     Node *innerNode = nodeInfo.innerNode();
1783     if (!innerNode || !innerNode->renderer())
1784         return false;
1785     
1786     Position pos(innerNode->renderer()->positionForPoint(point).deepEquivalent());
1787     if (pos.isNull())
1788         return false;
1789
1790     Node *n = selectionController()->start().node();
1791     while (n) {
1792         if (n == pos.node()) {
1793             if ((n == selectionController()->start().node() && pos.offset() < selectionController()->start().offset()) ||
1794                 (n == selectionController()->end().node() && pos.offset() > selectionController()->end().offset())) {
1795                 return false;
1796             }
1797             return true;
1798         }
1799         if (n == selectionController()->end().node())
1800             break;
1801         n = n->traverseNextNode();
1802     }
1803
1804    return false;
1805 }
1806
1807 void Frame::selectClosestWordFromMouseEvent(const PlatformMouseEvent& mouse, Node *innerNode)
1808 {
1809     Selection newSelection;
1810
1811     if (innerNode && innerNode->renderer() && mouseDownMayStartSelect() && innerNode->renderer()->shouldSelect()) {
1812         IntPoint vPoint = view()->viewportToContents(mouse.pos());
1813         VisiblePosition pos(innerNode->renderer()->positionForPoint(vPoint));
1814         if (pos.isNotNull()) {
1815             newSelection = Selection(pos);
1816             newSelection.expandUsingGranularity(WordGranularity);
1817         }
1818     }
1819     
1820     if (newSelection.isRange()) {
1821         d->m_selectionGranularity = WordGranularity;
1822         d->m_beganSelectingText = true;
1823     }
1824     
1825     if (shouldChangeSelection(newSelection))
1826         selectionController()->setSelection(newSelection);
1827 }
1828
1829 void Frame::handleMousePressEventDoubleClick(const MouseEventWithHitTestResults& event)
1830 {
1831     if (event.event().button() == LeftButton) {
1832         if (selectionController()->isRange())
1833             // A double-click when range is already selected
1834             // should not change the selection.  So, do not call
1835             // selectClosestWordFromMouseEvent, but do set
1836             // m_beganSelectingText to prevent handleMouseReleaseEvent
1837             // from setting caret selection.
1838             d->m_beganSelectingText = true;
1839         else
1840             selectClosestWordFromMouseEvent(event.event(), event.targetNode());
1841     }
1842 }
1843
1844 void Frame::handleMousePressEventTripleClick(const MouseEventWithHitTestResults& event)
1845 {
1846     Node *innerNode = event.targetNode();
1847     
1848     if (event.event().button() == LeftButton && innerNode && innerNode->renderer() &&
1849         mouseDownMayStartSelect() && innerNode->renderer()->shouldSelect()) {
1850         Selection newSelection;
1851         IntPoint vPoint = view()->viewportToContents(event.event().pos());
1852         VisiblePosition pos(innerNode->renderer()->positionForPoint(vPoint));
1853         if (pos.isNotNull()) {
1854             newSelection = Selection(pos);
1855             newSelection.expandUsingGranularity(ParagraphGranularity);
1856         }
1857         if (newSelection.isRange()) {
1858             d->m_selectionGranularity = ParagraphGranularity;
1859             d->m_beganSelectingText = true;
1860         }
1861         
1862         if (shouldChangeSelection(newSelection))
1863             selectionController()->setSelection(newSelection);
1864     }
1865 }
1866
1867 void Frame::handleMousePressEventSingleClick(const MouseEventWithHitTestResults& event)
1868 {
1869     Node *innerNode = event.targetNode();
1870     
1871     if (event.event().button() == LeftButton) {
1872         if (innerNode && innerNode->renderer() &&
1873             mouseDownMayStartSelect() && innerNode->renderer()->shouldSelect()) {
1874             
1875             // Extend the selection if the Shift key is down, unless the click is in a link.
1876             bool extendSelection = event.event().shiftKey() && !event.isOverLink();
1877
1878             // Don't restart the selection when the mouse is pressed on an
1879             // existing selection so we can allow for text dragging.
1880             IntPoint vPoint = view()->viewportToContents(event.event().pos());
1881             if (!extendSelection && isPointInsideSelection(vPoint))
1882                 return;
1883
1884             VisiblePosition visiblePos(innerNode->renderer()->positionForPoint(vPoint));
1885             if (visiblePos.isNull())
1886                 visiblePos = VisiblePosition(innerNode, innerNode->caretMinOffset(), DOWNSTREAM);
1887             Position pos = visiblePos.deepEquivalent();
1888             
1889             Selection newSelection = selectionController()->selection();
1890             if (extendSelection && newSelection.isCaretOrRange()) {
1891                 selectionController()->clearModifyBias();
1892                 
1893                 // See <rdar://problem/3668157> REGRESSION (Mail): shift-click deselects when selection 
1894                 // was created right-to-left
1895                 Position start = newSelection.start();
1896                 Position end = newSelection.end();
1897                 short before = Range::compareBoundaryPoints(pos.node(), pos.offset(), start.node(), start.offset());
1898                 if (before <= 0)
1899                     newSelection = Selection(pos, end);
1900                 else
1901                     newSelection = Selection(start, pos);
1902
1903                 if (d->m_selectionGranularity != CharacterGranularity)
1904                     newSelection.expandUsingGranularity(d->m_selectionGranularity);
1905                 d->m_beganSelectingText = true;
1906             } else {
1907                 newSelection = Selection(visiblePos);
1908                 d->m_selectionGranularity = CharacterGranularity;
1909             }
1910             
1911             if (shouldChangeSelection(newSelection))
1912                 selectionController()->setSelection(newSelection);
1913         }
1914     }
1915 }
1916
1917 void Frame::handleMousePressEvent(const MouseEventWithHitTestResults& event)
1918 {
1919     Node *innerNode = event.targetNode();
1920
1921     d->m_mousePressNode = innerNode;
1922     d->m_dragStartPos = event.event().pos();
1923
1924     if (event.event().button() == LeftButton || event.event().button() == MiddleButton) {
1925         d->m_bMousePressed = true;
1926         d->m_beganSelectingText = false;
1927
1928         if (event.event().clickCount() == 2) {
1929             handleMousePressEventDoubleClick(event);
1930             return;
1931         }
1932         if (event.event().clickCount() >= 3) {
1933             handleMousePressEventTripleClick(event);
1934             return;
1935         }
1936         handleMousePressEventSingleClick(event);
1937     }
1938 }
1939
1940 void Frame::handleMouseMoveEvent(const MouseEventWithHitTestResults& event)
1941 {
1942     // Mouse not pressed. Do nothing.
1943     if (!d->m_bMousePressed)
1944         return;
1945
1946     Node *innerNode = event.targetNode();
1947
1948     if (event.event().button() != 0 || !innerNode || !innerNode->renderer() || !mouseDownMayStartSelect() || !innerNode->renderer()->shouldSelect())
1949         return;
1950
1951     // handle making selection
1952     IntPoint vPoint = view()->viewportToContents(event.event().pos());
1953     VisiblePosition pos(innerNode->renderer()->positionForPoint(vPoint));
1954
1955     // Don't modify the selection if we're not on a node.
1956     if (pos.isNull())
1957         return;
1958
1959     // Restart the selection if this is the first mouse move. This work is usually
1960     // done in handleMousePressEvent, but not if the mouse press was on an existing selection.
1961     Selection newSelection = selectionController()->selection();
1962     selectionController()->clearModifyBias();
1963     
1964     if (!d->m_beganSelectingText) {
1965         d->m_beganSelectingText = true;
1966         newSelection = Selection(pos);
1967     }
1968
1969     newSelection.setExtent(pos);
1970     if (d->m_selectionGranularity != CharacterGranularity)
1971         newSelection.expandUsingGranularity(d->m_selectionGranularity);
1972
1973     if (shouldChangeSelection(newSelection))
1974         selectionController()->setSelection(newSelection);
1975 }
1976
1977 void Frame::handleMouseReleaseEvent(const MouseEventWithHitTestResults& event)
1978 {
1979     stopAutoscrollTimer();
1980     
1981     // Used to prevent mouseMoveEvent from initiating a drag before
1982     // the mouse is pressed again.
1983     d->m_bMousePressed = false;
1984   
1985     // Clear the selection if the mouse didn't move after the last mouse press.
1986     // We do this so when clicking on the selection, the selection goes away.
1987     // However, if we are editing, place the caret.
1988     if (mouseDownMayStartSelect() && !d->m_beganSelectingText
1989             && d->m_dragStartPos == event.event().pos()
1990             && selectionController()->isRange()) {
1991         Selection newSelection;
1992         Node *node = event.targetNode();
1993         if (node && node->isContentEditable() && node->renderer()) {
1994             IntPoint vPoint = view()->viewportToContents(event.event().pos());
1995             VisiblePosition pos = node->renderer()->positionForPoint(vPoint);
1996             newSelection = Selection(pos);
1997         }
1998         if (shouldChangeSelection(newSelection))
1999             selectionController()->setSelection(newSelection);
2000     }
2001
2002     notifyRendererOfSelectionChange(true);
2003
2004     selectFrameElementInParentIfFullySelected();
2005 }
2006
2007 void Frame::selectAll()
2008 {
2009     if (!d->m_doc)
2010         return;
2011     
2012     Node* root = selectionController()->isContentEditable() ? selectionController()->rootEditableElement() : d->m_doc->documentElement();
2013     selectContentsOfNode(root);
2014     selectFrameElementInParentIfFullySelected();
2015     notifyRendererOfSelectionChange(true);
2016 }
2017
2018 bool Frame::selectContentsOfNode(Node* node)
2019 {
2020     Selection newSelection(Selection::selectionFromContentsOfNode(node));
2021     if (shouldChangeSelection(newSelection)) {
2022         selectionController()->setSelection(newSelection);
2023         return true;
2024     }
2025     return false;
2026 }
2027
2028 bool Frame::shouldChangeSelection(const Selection& newSelection) const
2029 {
2030     return shouldChangeSelection(selectionController()->selection(), newSelection, newSelection.affinity(), false);
2031 }
2032
2033 bool Frame::shouldDeleteSelection(const Selection& newSelection) const
2034 {
2035     return true;
2036 }
2037
2038 bool Frame::shouldBeginEditing(const Range *range) const
2039 {
2040     return true;
2041 }
2042
2043 bool Frame::shouldEndEditing(const Range *range) const
2044 {
2045     return true;
2046 }
2047
2048 bool Frame::isContentEditable() const 
2049 {
2050     if (!d->m_doc)
2051         return false;
2052     return d->m_doc->inDesignMode();
2053 }
2054
2055 void Frame::textFieldDidBeginEditing(Element* input)
2056 {
2057 }
2058
2059 void Frame::textFieldDidEndEditing(Element* input)
2060 {
2061 }
2062
2063 void Frame::textDidChangeInTextField(Element* input)
2064 {
2065 }
2066
2067 bool Frame::doTextFieldCommandFromEvent(Element* input, const PlatformKeyboardEvent* evt)
2068 {
2069     return false;
2070 }
2071
2072 void Frame::textWillBeDeletedInTextField(Element* input)
2073 {
2074 }
2075
2076 void Frame::textDidChangeInTextArea(Element* input)
2077 {
2078 }
2079
2080 bool Frame::isSelectionInPasswordField()
2081 {
2082     Node* startNode = selectionController()->start().node();
2083     if (startNode)
2084         startNode = startNode->shadowAncestorNode();
2085     return startNode && startNode->hasTagName(inputTag) && static_cast<HTMLInputElement*>(startNode)->inputType() == HTMLInputElement::PASSWORD;
2086 }
2087   
2088 EditCommand* Frame::lastEditCommand()
2089 {
2090     return d->m_lastEditCommand.get();
2091 }
2092
2093 static void dispatchEditableContentChangedEvents(const EditCommand& command)
2094 {
2095      Element* startRoot = command.startingRootEditableElement();
2096      Element* endRoot = command.endingRootEditableElement();
2097      ExceptionCode ec;
2098      if (startRoot)
2099          startRoot->dispatchEvent(new Event(khtmlEditableContentChangedEvent, false, false), ec, true);
2100      if (endRoot && endRoot != startRoot)
2101          endRoot->dispatchEvent(new Event(khtmlEditableContentChangedEvent, false, false), ec, true);
2102 }
2103
2104 void Frame::appliedEditing(PassRefPtr<EditCommand> cmd)
2105 {
2106     dispatchEditableContentChangedEvents(*cmd);
2107  
2108     Selection newSelection(cmd->endingSelection());
2109     if (shouldChangeSelection(newSelection))
2110         selectionController()->setSelection(newSelection, false);
2111     
2112     // Now set the typing style from the command. Clear it when done.
2113     // This helps make the case work where you completely delete a piece
2114     // of styled text and then type a character immediately after.
2115     // That new character needs to take on the style of the just-deleted text.
2116     // FIXME: Improve typing style.
2117     // See this bug: <rdar://problem/3769899> Implementation of typing style needs improvement
2118     if (cmd->typingStyle()) {
2119         setTypingStyle(cmd->typingStyle());
2120         cmd->setTypingStyle(0);
2121     }
2122
2123     // Command will be equal to last edit command only in the case of typing
2124     if (d->m_lastEditCommand == cmd)
2125         assert(cmd->isTypingCommand());
2126     else {
2127         // Only register a new undo command if the command passed in is
2128         // different from the last command
2129         d->m_lastEditCommand = cmd.get();
2130         registerCommandForUndo(cmd);
2131     }
2132     respondToChangedContents(newSelection);
2133 }
2134
2135 void Frame::unappliedEditing(PassRefPtr<EditCommand> cmd)
2136 {
2137     dispatchEditableContentChangedEvents(*cmd);
2138
2139     Selection newSelection(cmd->startingSelection());
2140     if (shouldChangeSelection(newSelection))
2141         selectionController()->setSelection(newSelection, true);
2142         
2143     d->m_lastEditCommand = 0;
2144     registerCommandForRedo(cmd);
2145     respondToChangedContents(newSelection);
2146 }
2147
2148 void Frame::reappliedEditing(PassRefPtr<EditCommand> cmd)
2149 {
2150     dispatchEditableContentChangedEvents(*cmd);
2151
2152     Selection newSelection(cmd->endingSelection());
2153     if (shouldChangeSelection(newSelection))
2154         selectionController()->setSelection(newSelection, true);
2155         
2156     d->m_lastEditCommand = 0;
2157     registerCommandForUndo(cmd);
2158     respondToChangedContents(newSelection);
2159 }
2160
2161 CSSMutableStyleDeclaration *Frame::typingStyle() const
2162 {
2163     return d->m_typingStyle.get();
2164 }
2165
2166 void Frame::setTypingStyle(CSSMutableStyleDeclaration *style)
2167 {
2168     d->m_typingStyle = style;
2169 }
2170
2171 void Frame::clearTypingStyle()
2172 {
2173     d->m_typingStyle = 0;
2174 }
2175
2176 JSValue* Frame::executeScript(const String& filename, int baseLine, Node* n, const String& script)
2177 {
2178     // FIXME: This is missing stuff that the other executeScript has.
2179     // --> d->m_runningScripts and submitFormAgain.
2180     // Why is that OK?
2181     KJSProxy* proxy = jScript();
2182     if (!proxy)
2183         return 0;
2184     JSValue* ret = proxy->evaluate(filename, baseLine, script, n);
2185     Document::updateDocumentsRendering();
2186     return ret;
2187 }
2188
2189 Frame *Frame::opener()
2190 {
2191     return d->m_opener;
2192 }
2193
2194 void Frame::setOpener(Frame* opener)
2195 {
2196     if (d->m_opener)
2197         d->m_opener->d->m_openedFrames.remove(this);
2198     if (opener)
2199         opener->d->m_openedFrames.add(this);
2200     d->m_opener = opener;
2201 }
2202
2203 bool Frame::openedByJS()
2204 {
2205     return d->m_openedByJS;
2206 }
2207
2208 void Frame::setOpenedByJS(bool _openedByJS)
2209 {
2210     d->m_openedByJS = _openedByJS;
2211 }
2212
2213 bool Frame::tabsToLinks() const
2214 {
2215     return true;
2216 }
2217
2218 bool Frame::tabsToAllControls() const
2219 {
2220     return true;
2221 }
2222
2223 void Frame::copyToPasteboard()
2224 {
2225     issueCopyCommand();
2226 }
2227
2228 void Frame::cutToPasteboard()
2229 {
2230     issueCutCommand();
2231 }
2232
2233 void Frame::pasteFromPasteboard()
2234 {
2235     issuePasteCommand();
2236 }
2237
2238 void Frame::pasteAndMatchStyle()
2239 {
2240     issuePasteAndMatchStyleCommand();
2241 }
2242
2243 bool Frame::mayCopy()
2244 {
2245     return !isSelectionInPasswordField();
2246 }
2247
2248 void Frame::transpose()
2249 {
2250     issueTransposeCommand();
2251 }
2252
2253 void Frame::redo()
2254 {
2255     issueRedoCommand();
2256 }
2257
2258 void Frame::undo()
2259 {
2260     issueUndoCommand();
2261 }
2262
2263
2264 void Frame::computeAndSetTypingStyle(CSSStyleDeclaration *style, EditAction editingAction)
2265 {
2266     if (!style || style->length() == 0) {
2267         clearTypingStyle();
2268         return;
2269     }
2270
2271     // Calculate the current typing style.
2272     RefPtr<CSSMutableStyleDeclaration> mutableStyle = style->makeMutable();
2273     if (typingStyle()) {
2274         typingStyle()->merge(mutableStyle.get());
2275         mutableStyle = typingStyle();
2276     }
2277
2278     Node *node = selectionController()->selection().visibleStart().deepEquivalent().node();
2279     CSSComputedStyleDeclaration computedStyle(node);
2280     computedStyle.diff(mutableStyle.get());
2281     
2282     // Handle block styles, substracting these from the typing style.
2283     RefPtr<CSSMutableStyleDeclaration> blockStyle = mutableStyle->copyBlockProperties();
2284     blockStyle->diff(mutableStyle.get());
2285     if (document() && blockStyle->length() > 0)
2286         applyCommand(new ApplyStyleCommand(document(), blockStyle.get(), editingAction));
2287     
2288     // Set the remaining style as the typing style.
2289     d->m_typingStyle = mutableStyle.release();
2290 }
2291
2292 void Frame::applyStyle(CSSStyleDeclaration *style, EditAction editingAction)
2293 {
2294     switch (selectionController()->state()) {
2295         case Selection::NONE:
2296             // do nothing
2297             break;
2298         case Selection::CARET: {
2299             computeAndSetTypingStyle(style, editingAction);
2300             break;
2301         }
2302         case Selection::RANGE:
2303             if (document() && style)
2304                 applyCommand(new ApplyStyleCommand(document(), style, editingAction));
2305             break;
2306     }
2307 }
2308
2309 void Frame::applyParagraphStyle(CSSStyleDeclaration *style, EditAction editingAction)
2310 {
2311     switch (selectionController()->state()) {
2312         case Selection::NONE:
2313             // do nothing
2314             break;
2315         case Selection::CARET:
2316         case Selection::RANGE:
2317             if (document() && style)
2318                 applyCommand(new ApplyStyleCommand(document(), style, editingAction, ApplyStyleCommand::ForceBlockProperties));
2319             break;
2320     }
2321 }
2322
2323 static void updateState(CSSMutableStyleDeclaration *desiredStyle, CSSComputedStyleDeclaration *computedStyle, bool& atStart, Frame::TriState& state)
2324 {
2325     DeprecatedValueListConstIterator<CSSProperty> end;
2326     for (DeprecatedValueListConstIterator<CSSProperty> it = desiredStyle->valuesIterator(); it != end; ++it) {
2327         int propertyID = (*it).id();
2328         String desiredProperty = desiredStyle->getPropertyValue(propertyID);
2329         String computedProperty = computedStyle->getPropertyValue(propertyID);
2330         Frame::TriState propertyState = equalIgnoringCase(desiredProperty, computedProperty)
2331             ? Frame::trueTriState : Frame::falseTriState;
2332         if (atStart) {
2333             state = propertyState;
2334             atStart = false;
2335         } else if (state != propertyState) {
2336             state = Frame::mixedTriState;
2337             break;
2338         }
2339     }
2340 }
2341
2342 Frame::TriState Frame::selectionListState() const
2343 {
2344     TriState state = falseTriState;
2345
2346     if (!selectionController()->isRange()) {
2347         Node* selectionNode = selectionController()->selection().start().node();
2348         if (enclosingList(selectionNode))
2349             return trueTriState;
2350     } else {
2351         //FIXME: Support ranges
2352     }
2353
2354     return state;
2355 }
2356
2357 Frame::TriState Frame::selectionHasStyle(CSSStyleDeclaration *style) const
2358 {
2359     bool atStart = true;
2360     TriState state = falseTriState;
2361
2362     RefPtr<CSSMutableStyleDeclaration> mutableStyle = style->makeMutable();
2363
2364     if (!selectionController()->isRange()) {
2365         Node* nodeToRemove;
2366         RefPtr<CSSComputedStyleDeclaration> selectionStyle = selectionComputedStyle(nodeToRemove);
2367         if (!selectionStyle)
2368             return falseTriState;
2369         updateState(mutableStyle.get(), selectionStyle.get(), atStart, state);
2370         if (nodeToRemove) {
2371             ExceptionCode ec = 0;
2372             nodeToRemove->remove(ec);
2373             assert(ec == 0);
2374         }
2375     } else {
2376         for (Node* node = selectionController()->start().node(); node; node = node->traverseNextNode()) {
2377             RefPtr<CSSComputedStyleDeclaration> computedStyle = new CSSComputedStyleDeclaration(node);
2378             if (computedStyle)
2379                 updateState(mutableStyle.get(), computedStyle.get(), atStart, state);
2380             if (state == mixedTriState)
2381                 break;
2382             if (node == selectionController()->end().node())
2383                 break;
2384         }
2385     }
2386
2387     return state;
2388 }
2389
2390 bool Frame::selectionStartHasStyle(CSSStyleDeclaration *style) const
2391 {
2392     Node* nodeToRemove;
2393     RefPtr<CSSStyleDeclaration> selectionStyle = selectionComputedStyle(nodeToRemove);
2394     if (!selectionStyle)
2395         return false;
2396
2397     RefPtr<CSSMutableStyleDeclaration> mutableStyle = style->makeMutable();
2398
2399     bool match = true;
2400     DeprecatedValueListConstIterator<CSSProperty> end;
2401     for (DeprecatedValueListConstIterator<CSSProperty> it = mutableStyle->valuesIterator(); it != end; ++it) {
2402         int propertyID = (*it).id();
2403         if (!equalIgnoringCase(mutableStyle->getPropertyValue(propertyID), selectionStyle->getPropertyValue(propertyID))) {
2404             match = false;
2405             break;
2406         }
2407     }
2408
2409     if (nodeToRemove) {
2410         ExceptionCode ec = 0;
2411         nodeToRemove->remove(ec);
2412         assert(ec == 0);
2413     }
2414
2415     return match;
2416 }
2417
2418 String Frame::selectionStartStylePropertyValue(int stylePropertyID) const
2419 {
2420     Node *nodeToRemove;
2421     RefPtr<CSSStyleDeclaration> selectionStyle = selectionComputedStyle(nodeToRemove);
2422     if (!selectionStyle)
2423         return String();
2424
2425     String value = selectionStyle->getPropertyValue(stylePropertyID);
2426
2427     if (nodeToRemove) {
2428         ExceptionCode ec = 0;
2429         nodeToRemove->remove(ec);
2430         assert(ec == 0);
2431     }
2432
2433     return value;
2434 }
2435
2436 CSSComputedStyleDeclaration *Frame::selectionComputedStyle(Node *&nodeToRemove) const
2437 {
2438     nodeToRemove = 0;
2439
2440     if (!document())
2441         return 0;
2442
2443     if (selectionController()->isNone())
2444         return 0;
2445
2446     RefPtr<Range> range(selectionController()->toRange());
2447     Position pos = range->editingStartPosition();
2448
2449     Element *elem = pos.element();
2450     if (!elem)
2451         return 0;
2452     
2453     RefPtr<Element> styleElement = elem;
2454     ExceptionCode ec = 0;
2455
2456     if (d->m_typingStyle) {
2457         styleElement = document()->createElementNS(xhtmlNamespaceURI, "span", ec);
2458         assert(ec == 0);
2459
2460         styleElement->setAttribute(styleAttr, d->m_typingStyle->cssText().impl(), ec);
2461         assert(ec == 0);
2462         
2463         styleElement->appendChild(document()->createEditingTextNode(""), ec);
2464         assert(ec == 0);
2465
2466         if (elem->renderer() && elem->renderer()->canHaveChildren()) {
2467             elem->appendChild(styleElement, ec);
2468         } else {
2469             Node *parent = elem->parent();
2470             Node *next = elem->nextSibling();
2471
2472             if (next) {
2473                 parent->insertBefore(styleElement, next, ec);
2474             } else {
2475                 parent->appendChild(styleElement, ec);
2476             }
2477         }
2478         assert(ec == 0);
2479
2480         nodeToRemove = styleElement.get();
2481     }
2482
2483     return new CSSComputedStyleDeclaration(styleElement);
2484 }
2485
2486 void Frame::applyEditingStyleToBodyElement() const
2487 {
2488     if (!d->m_doc)
2489         return;
2490         
2491     RefPtr<NodeList> list = d->m_doc->getElementsByTagName("body");
2492     unsigned len = list->length();
2493     for (unsigned i = 0; i < len; i++) {
2494         applyEditingStyleToElement(static_cast<Element*>(list->item(i)));    
2495     }
2496 }
2497
2498 void Frame::removeEditingStyleFromBodyElement() const
2499 {
2500     if (!d->m_doc)
2501         return;
2502         
2503     RefPtr<NodeList> list = d->m_doc->getElementsByTagName("body");
2504     unsigned len = list->length();
2505     for (unsigned i = 0; i < len; i++) {
2506         removeEditingStyleFromElement(static_cast<Element*>(list->item(i)));    
2507     }
2508 }
2509
2510 void Frame::applyEditingStyleToElement(Element* element) const
2511 {
2512     if (!element)
2513         return;
2514
2515     CSSStyleDeclaration* style = element->style();
2516     ASSERT(style);
2517
2518     ExceptionCode ec = 0;
2519     style->setProperty(CSS_PROP_WORD_WRAP, "break-word", false, ec);
2520     ASSERT(ec == 0);
2521     style->setProperty(CSS_PROP__WEBKIT_NBSP_MODE, "space", false, ec);
2522     ASSERT(ec == 0);
2523     style->setProperty(CSS_PROP__WEBKIT_LINE_BREAK, "after-white-space", false, ec);
2524     ASSERT(ec == 0);
2525 }
2526
2527 void Frame::removeEditingStyleFromElement(Element*) const
2528 {
2529 }
2530
2531 bool Frame::isCharacterSmartReplaceExempt(UChar, bool)
2532 {
2533     // no smart replace
2534     return true;
2535 }
2536
2537 #ifndef NDEBUG
2538 static HashSet<Frame*> lifeSupportSet;
2539 #endif
2540
2541 void Frame::endAllLifeSupport()
2542 {
2543 #ifndef NDEBUG
2544     HashSet<Frame*> lifeSupportCopy = lifeSupportSet;
2545     HashSet<Frame*>::iterator end = lifeSupportCopy.end();
2546     for (HashSet<Frame*>::iterator it = lifeSupportCopy.begin(); it != end; ++it)
2547         (*it)->endLifeSupport();
2548 #endif
2549 }
2550
2551 void Frame::keepAlive()
2552 {
2553     if (d->m_lifeSupportTimer.isActive())
2554         return;
2555     ref();
2556 #ifndef NDEBUG
2557     lifeSupportSet.add(this);
2558 #endif
2559     d->m_lifeSupportTimer.startOneShot(0);
2560 }
2561
2562 void Frame::endLifeSupport()
2563 {
2564     if (!d->m_lifeSupportTimer.isActive())
2565         return;
2566     d->m_lifeSupportTimer.stop();
2567 #ifndef NDEBUG
2568     lifeSupportSet.remove(this);
2569 #endif
2570     deref();
2571 }
2572
2573 void Frame::lifeSupportTimerFired(Timer<Frame>*)
2574 {
2575 #ifndef NDEBUG
2576     lifeSupportSet.remove(this);
2577 #endif
2578     deref();
2579 }
2580
2581 // Workaround for the fact that it's hard to delete a frame.
2582 // Call this after doing user-triggered selections to make it easy to delete the frame you entirely selected.
2583 // Can't do this implicitly as part of every setSelection call because in some contexts it might not be good
2584 // for the focus to move to another frame. So instead we call it from places where we are selecting with the
2585 // mouse or the keyboard after setting the selection.
2586 void Frame::selectFrameElementInParentIfFullySelected()
2587 {
2588     // Find the parent frame; if there is none, then we have nothing to do.
2589     Frame *parent = tree()->parent();
2590     if (!parent)
2591         return;
2592     FrameView *parentView = parent->view();
2593     if (!parentView)
2594         return;
2595
2596     // Check if the selection contains the entire frame contents; if not, then there is nothing to do.
2597     if (!selectionController()->isRange())
2598         return;
2599     if (!isStartOfDocument(selectionController()->selection().visibleStart()))
2600         return;
2601     if (!isEndOfDocument(selectionController()->selection().visibleEnd()))
2602         return;
2603
2604     // Get to the <iframe> or <frame> (or even <object>) element in the parent frame.
2605     Document *doc = document();
2606     if (!doc)
2607         return;
2608     Element *ownerElement = doc->ownerElement();
2609     if (!ownerElement)
2610         return;
2611     Node *ownerElementParent = ownerElement->parentNode();
2612     if (!ownerElementParent)
2613         return;
2614         
2615     // 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.
2616     if (!ownerElementParent->isContentEditable())
2617         return;
2618
2619     // Create compute positions before and after the element.
2620     unsigned ownerElementNodeIndex = ownerElement->nodeIndex();
2621     VisiblePosition beforeOwnerElement(VisiblePosition(ownerElementParent, ownerElementNodeIndex, SEL_DEFAULT_AFFINITY));
2622     VisiblePosition afterOwnerElement(VisiblePosition(ownerElementParent, ownerElementNodeIndex + 1, VP_UPSTREAM_IF_POSSIBLE));
2623
2624     // Focus on the parent frame, and then select from before this element to after.
2625     Selection newSelection(beforeOwnerElement, afterOwnerElement);
2626     if (parent->shouldChangeSelection(newSelection)) {
2627         parentView->setFocus();
2628         parent->selectionController()->setSelection(newSelection);
2629     }
2630 }
2631
2632 void Frame::handleFallbackContent()
2633 {
2634     Element* owner = ownerElement();
2635     if (!owner || !owner->hasTagName(objectTag))
2636         return;
2637     static_cast<HTMLObjectElement*>(owner)->renderFallbackContent();
2638 }
2639
2640 void Frame::setSettings(Settings *settings)
2641 {
2642     d->m_settings = settings;
2643 }
2644
2645 void Frame::provisionalLoadStarted()
2646 {
2647     // we don't want to wait until we get an actual http response back
2648     // to cancel pending redirects, otherwise they might fire before
2649     // that happens.
2650     cancelRedirection(true);
2651 }
2652
2653 bool Frame::userGestureHint()
2654 {
2655     Frame *rootFrame = this;
2656     while (rootFrame->tree()->parent())
2657         rootFrame = rootFrame->tree()->parent();
2658
2659     if (rootFrame->jScript())
2660         return rootFrame->jScript()->interpreter()->wasRunByUserGesture();
2661
2662     return true; // If JavaScript is disabled, a user gesture must have initiated the navigation
2663 }
2664
2665 RenderObject *Frame::renderer() const
2666 {
2667     Document *doc = document();
2668     return doc ? doc->renderer() : 0;
2669 }
2670
2671 Element* Frame::ownerElement()
2672 {
2673     return d->m_ownerElement;
2674 }
2675
2676 RenderPart* Frame::ownerRenderer()
2677 {
2678     Element* ownerElement = d->m_ownerElement;
2679     if (!ownerElement)
2680         return 0;
2681     return static_cast<RenderPart*>(ownerElement->renderer());
2682 }
2683
2684 IntRect Frame::selectionRect() const
2685 {
2686     RenderView *root = static_cast<RenderView*>(renderer());
2687     if (!root)
2688         return IntRect();
2689
2690     return root->selectionRect();
2691 }
2692
2693 // returns FloatRect because going through IntRect would truncate any floats
2694 FloatRect Frame::visibleSelectionRect() const
2695 {
2696     if (!d->m_view)
2697         return FloatRect();
2698     
2699     return intersection(selectionRect(), d->m_view->visibleContentRect());
2700 }
2701
2702 bool Frame::isFrameSet() const
2703 {
2704     Document* document = d->m_doc.get();
2705     if (!document || !document->isHTMLDocument())
2706         return false;
2707     Node *body = static_cast<HTMLDocument*>(document)->body();
2708     return body && body->renderer() && body->hasTagName(framesetTag);
2709 }
2710
2711 bool Frame::openURL(const KURL& URL)
2712 {
2713     ASSERT_NOT_REACHED();
2714     return true;
2715 }
2716
2717 void Frame::didNotOpenURL(const KURL& URL)
2718 {
2719     if (d->m_submittedFormURL == URL)
2720         d->m_submittedFormURL = KURL();
2721 }
2722
2723 // Scans logically forward from "start", including any child frames
2724 static HTMLFormElement *scanForForm(Node *start)
2725 {
2726     Node *n;
2727     for (n = start; n; n = n->traverseNextNode()) {
2728         if (n->hasTagName(formTag))
2729             return static_cast<HTMLFormElement*>(n);
2730         else if (n->isHTMLElement() && static_cast<HTMLElement*>(n)->isGenericFormElement())
2731             return static_cast<HTMLGenericFormElement*>(n)->form();
2732         else if (n->hasTagName(frameTag) || n->hasTagName(iframeTag)) {
2733             Node *childDoc = static_cast<HTMLFrameElement*>(n)->contentDocument();
2734             if (HTMLFormElement *frameResult = scanForForm(childDoc))
2735                 return frameResult;
2736         }
2737     }
2738     return 0;
2739 }
2740
2741 // We look for either the form containing the current focus, or for one immediately after it
2742 HTMLFormElement *Frame::currentForm() const
2743 {
2744     // start looking either at the active (first responder) node, or where the selection is
2745     Node *start = d->m_doc ? d->m_doc->focusNode() : 0;
2746     if (!start)
2747         start = selectionController()->start().node();
2748     
2749     // try walking up the node tree to find a form element
2750     Node *n;
2751     for (n = start; n; n = n->parentNode()) {
2752         if (n->hasTagName(formTag))
2753             return static_cast<HTMLFormElement*>(n);
2754         else if (n->isHTMLElement()
2755                    && static_cast<HTMLElement*>(n)->isGenericFormElement())
2756             return static_cast<HTMLGenericFormElement*>(n)->form();
2757     }
2758     
2759     // try walking forward in the node tree to find a form element
2760     return start ? scanForForm(start) : 0;
2761 }
2762
2763 void Frame::setEncoding(const String& name, bool userChosen)
2764 {
2765     if (!d->m_workingURL.isEmpty())
2766         receivedFirstData();
2767     d->m_encoding = name;
2768     d->m_haveEncoding = userChosen;
2769 }
2770
2771 void Frame::addData(const char *bytes, int length)
2772 {
2773     ASSERT(d->m_workingURL.isEmpty());
2774     ASSERT(d->m_doc);
2775     ASSERT(d->m_doc->parsing());
2776     write(bytes, length);
2777 }
2778
2779 // FIXME: should this go in SelectionController?
2780 void Frame::revealSelection(const RenderLayer::ScrollAlignment& alignment) const
2781 {
2782     IntRect rect;
2783     
2784     switch (selectionController()->state()) {
2785         case Selection::NONE:
2786             return;
2787             
2788         case Selection::CARET:
2789             rect = selectionController()->caretRect();
2790             break;
2791             
2792         case Selection::RANGE:
2793             rect = selectionRect();
2794             break;
2795     }
2796
2797     Position start = selectionController()->start();
2798     Position end = selectionController()->end();
2799
2800     ASSERT(start.node());
2801     if (start.node() && start.node()->renderer()) {
2802         RenderLayer *layer = start.node()->renderer()->enclosingLayer();
2803         if (layer) {
2804             ASSERT(!end.node() || !end.node()->renderer() 
2805                    || (end.node()->renderer()->enclosingLayer() == layer));
2806             layer->scrollRectToVisible(rect, alignment, alignment);
2807         }
2808     }
2809 }
2810
2811 void Frame::revealCaret(const RenderLayer::ScrollAlignment& alignment) const
2812 {
2813     if (!hasSelection())
2814         return;
2815
2816     Position extent = selectionController()->extent();
2817     if (extent.node() && extent.node()->renderer()) {
2818         IntRect extentRect = VisiblePosition(extent).caretRect();
2819         RenderLayer* layer = extent.node()->renderer()->enclosingLayer();
2820         if (layer)
2821             layer->scrollRectToVisible(extentRect, alignment, alignment);
2822     }
2823 }
2824
2825 // FIXME: should this be here?
2826 bool Frame::scrollOverflow(ScrollDirection direction, ScrollGranularity granularity)
2827 {
2828     if (!document()) {
2829         return false;
2830     }
2831     
2832     Node *node = document()->focusNode();
2833     if (node == 0) {
2834         node = d->m_mousePressNode.get();
2835     }
2836     
2837     if (node != 0) {
2838         RenderObject *r = node->renderer();
2839         if (r != 0) {
2840             return r->scroll(direction, granularity);
2841         }
2842     }
2843     
2844     return false;
2845 }
2846
2847 void Frame::handleAutoscroll(RenderLayer* layer)
2848 {
2849     if (d->m_autoscrollTimer.isActive())
2850         return;
2851     d->m_autoscrollLayer = layer;
2852     startAutoscrollTimer();
2853 }
2854
2855 void Frame::autoscrollTimerFired(Timer<Frame>*)
2856 {
2857     if (!d->m_bMousePressed){
2858         stopAutoscrollTimer();
2859         return;
2860     }
2861     if (d->m_autoscrollLayer) {
2862         d->m_autoscrollLayer->autoscroll();
2863     } 
2864 }
2865
2866 RenderObject::NodeInfo Frame::nodeInfoAtPoint(const IntPoint& point, bool allowShadowContent)
2867 {
2868     RenderObject::NodeInfo nodeInfo(true, true);
2869     renderer()->layer()->hitTest(nodeInfo, point);
2870
2871     Node *n;
2872     Widget *widget = 0;
2873     IntPoint widgetPoint(point);
2874     
2875     while (true) {
2876         n = nodeInfo.innerNode();
2877         if (!n || !n->renderer() || !n->renderer()->isWidget())
2878             break;
2879         widget = static_cast<RenderWidget*>(n->renderer())->widget();
2880         if (!widget || !widget->isFrameView())
2881             break;
2882         Frame* frame = static_cast<HTMLFrameElement*>(n)->contentFrame();
2883         if (!frame || !frame->renderer())
2884             break;
2885         int absX, absY;
2886         n->renderer()->absolutePosition(absX, absY, true);
2887         FrameView *view = static_cast<FrameView*>(widget);
2888         widgetPoint.setX(widgetPoint.x() - absX + view->contentsX());
2889         widgetPoint.setY(widgetPoint.y() - absY + view->contentsY());
2890
2891         RenderObject::NodeInfo widgetNodeInfo(true, true);
2892         frame->renderer()->layer()->hitTest(widgetNodeInfo, widgetPoint);
2893         nodeInfo = widgetNodeInfo;
2894     }
2895     
2896     if (!allowShadowContent) {
2897         Node* node = nodeInfo.innerNode();
2898         if (node)
2899             node = node->shadowAncestorNode();
2900         nodeInfo.setInnerNode(node);
2901         node = nodeInfo.innerNonSharedNode();
2902         if (node)
2903             node = node->shadowAncestorNode();
2904         nodeInfo.setInnerNonSharedNode(node); 
2905     }
2906     return nodeInfo;
2907 }
2908
2909 bool Frame::hasSelection()
2910 {
2911     if (selectionController()->isNone())
2912         return false;
2913
2914     // If a part has a selection, it should also have a document.        
2915     ASSERT(document());
2916
2917     return true;
2918 }
2919
2920 void Frame::startAutoscrollTimer()
2921 {
2922     d->m_autoscrollTimer.startRepeating(autoscrollInterval);
2923 }
2924
2925 void Frame::stopAutoscrollTimer()
2926 {
2927     d->m_autoscrollLayer = 0;
2928     d->m_autoscrollTimer.stop();
2929 }
2930
2931 // FIXME: why is this here instead of on the FrameView?
2932 void Frame::paint(GraphicsContext* p, const IntRect& rect)
2933 {
2934 #ifndef NDEBUG
2935     bool fillWithRed;
2936     if (!document() || document()->printing())
2937         fillWithRed = false; // Printing, don't fill with red (can't remember why).
2938     else if (document()->ownerElement())
2939         fillWithRed = false; // Subframe, don't fill with red.
2940     else if (view() && view()->isTransparent())
2941         fillWithRed = false; // Transparent, don't fill with red.
2942     else if (d->m_paintRestriction == PaintRestrictionSelectionOnly || d->m_paintRestriction == PaintRestrictionSelectionOnlyWhiteText)
2943         fillWithRed = false; // Selections are transparent, don't fill with red.
2944     else if (d->m_elementToDraw)
2945         fillWithRed = false; // Element images are transparent, don't fill with red.
2946     else
2947         fillWithRed = true;
2948     
2949     if (fillWithRed)
2950         p->fillRect(rect, Color(0xFF, 0, 0));
2951 #endif
2952     
2953     if (renderer()) {
2954         // d->m_elementToDraw is used to draw only one element
2955         RenderObject *eltRenderer = d->m_elementToDraw ? d->m_elementToDraw->renderer() : 0;
2956         if (d->m_paintRestriction == PaintRestrictionNone)
2957             renderer()->document()->invalidateRenderedRectsForMarkersInRect(rect);
2958         renderer()->layer()->paint(p, rect, d->m_paintRestriction, eltRenderer);
2959
2960 #if __APPLE__
2961         // Regions may have changed as a result of the visibility/z-index of element changing.
2962         if (renderer()->document()->dashboardRegionsDirty())
2963             renderer()->view()->frameView()->updateDashboardRegions();
2964 #endif
2965     } else
2966         LOG_ERROR("called Frame::paint with nil renderer");
2967 }
2968
2969 #if __APPLE__
2970
2971 void Frame::adjustPageHeight(float *newBottom, float oldTop, float oldBottom, float bottomLimit)
2972 {
2973     RenderView *root = static_cast<RenderView*>(document()->renderer());
2974     if (root) {
2975         // Use a context with painting disabled.
2976         GraphicsContext context(0);
2977         root->setTruncatedAt((int)floorf(oldBottom));
2978         IntRect dirtyRect(0, (int)floorf(oldTop), root->docWidth(), (int)ceilf(oldBottom - oldTop));
2979         root->layer()->paint(&context, dirtyRect);
2980         *newBottom = root->bestTruncatedAt();
2981         if (*newBottom == 0)
2982             *newBottom = oldBottom;
2983     } else
2984         *newBottom = oldBottom;
2985 }
2986
2987 #endif
2988
2989 PausedTimeouts *Frame::pauseTimeouts()
2990 {
2991 #ifdef SVG_SUPPORT
2992     if (d->m_doc && d->m_doc->svgExtensions())
2993         d->m_doc->accessSVGExtensions()->pauseAnimations();
2994 #endif
2995
2996     if (d->m_doc && d->m_jscript) {
2997         if (Window* w = Window::retrieveWindow(this))
2998             return w->pauseTimeouts();
2999     }
3000     return 0;
3001 }
3002
3003 void Frame::resumeTimeouts(PausedTimeouts* t)
3004 {
3005 #ifdef SVG_SUPPORT
3006     if (d->m_doc && d->m_doc->svgExtensions())
3007         d->m_doc->accessSVGExtensions()->unpauseAnimations();
3008 #endif
3009
3010     if (d->m_doc && d->m_jscript && d->m_bJScriptEnabled) {
3011         if (Window* w = Window::retrieveWindow(this))
3012             w->resumeTimeouts(t);
3013     }
3014 }
3015
3016 bool Frame::canCachePage()
3017 {
3018     // Only save page state if:
3019     // 1.  We're not a frame or frameset.
3020     // 2.  The page has no unload handler.
3021     // 3.  The page has no password fields.
3022     // 4.  The URL for the page is not https.
3023     // 5.  The page has no applets.
3024     if (tree()->childCount() || d->m_plugins.size() ||
3025         tree()->parent() ||
3026         d->m_url.protocol().startsWith("https") || 
3027         (d->m_doc && (d->m_doc->applets()->length() != 0 ||
3028                       d->m_doc->hasWindowEventListener(unloadEvent) ||
3029                       d->m_doc->hasPasswordField()))) {
3030         return false;
3031     }
3032     return true;
3033 }
3034
3035 void Frame::saveWindowProperties(KJS::SavedProperties *windowProperties)
3036 {
3037     Window *window = Window::retrieveWindow(this);
3038     if (window)
3039         window->saveProperties(*windowProperties);
3040 }
3041
3042 void Frame::saveLocationProperties(SavedProperties *locationProperties)
3043 {
3044     Window *window = Window::retrieveWindow(this);
3045     if (window) {
3046         JSLock lock;
3047         Location *location = window->location();
3048         location->saveProperties(*locationProperties);
3049     }
3050 }
3051
3052 void Frame::restoreWindowProperties(SavedProperties *windowProperties)
3053 {
3054     Window *window = Window::retrieveWindow(this);
3055     if (window)
3056         window->restoreProperties(*windowProperties);
3057 }
3058
3059 void Frame::restoreLocationProperties(SavedProperties *locationProperties)
3060 {
3061     Window *window = Window::retrieveWindow(this);
3062     if (window) {
3063         JSLock lock;
3064         Location *location = window->location();
3065         location->restoreProperties(*locationProperties);
3066     }
3067 }
3068
3069 void Frame::saveInterpreterBuiltins(SavedBuiltins& interpreterBuiltins)
3070 {
3071     if (jScript())
3072         jScript()->interpreter()->saveBuiltins(interpreterBuiltins);
3073 }
3074
3075 void Frame::restoreInterpreterBuiltins(const SavedBuiltins& interpreterBuiltins)
3076 {
3077     if (jScript())
3078         jScript()->interpreter()->restoreBuiltins(interpreterBuiltins);
3079 }
3080
3081 Frame *Frame::frameForWidget(const Widget *widget)
3082 {
3083     ASSERT_ARG(widget, widget);
3084     
3085     Node *node = nodeForWidget(widget);
3086     if (node)
3087         return frameForNode(node);
3088     
3089     // Assume all widgets are either form controls, or FrameViews.
3090     ASSERT(widget->isFrameView());
3091     return static_cast<const FrameView*>(widget)->frame();
3092 }
3093
3094 Frame *Frame::frameForNode(Node *node)
3095 {
3096     ASSERT_ARG(node, node);
3097     return node->document()->frame();
3098 }
3099
3100 Node* Frame::nodeForWidget(const Widget* widget)
3101 {
3102     ASSERT_ARG(widget, widget);
3103     WidgetClient* client = widget->client();
3104     if (!client)
3105         return 0;
3106     return client->element(const_cast<Widget*>(widget));
3107 }
3108
3109 void Frame::clearDocumentFocus(Widget *widget)
3110 {
3111     Node *node = nodeForWidget(widget);
3112     ASSERT(node);
3113     node->document()->setFocusNode(0);
3114 }
3115
3116 void Frame::updatePolicyBaseURL()
3117 {
3118     if (tree()->parent() && tree()->parent()->document())
3119         setPolicyBaseURL(tree()->parent()->document()->policyBaseURL());
3120     else
3121         setPolicyBaseURL(d->m_url.url());
3122 }
3123
3124 void Frame::setPolicyBaseURL(const String& s)
3125 {
3126     if (document())
3127         document()->setPolicyBaseURL(s);
3128     for (Frame* child = tree()->firstChild(); child; child = child->tree()->nextSibling())
3129         child->setPolicyBaseURL(s);
3130 }
3131
3132 void Frame::forceLayout()
3133 {
3134     FrameView *v = d->m_view.get();
3135     if (v) {
3136         v->layout(false);
3137         // We cannot unschedule a pending relayout, since the force can be called with
3138         // a tiny rectangle from a drawRect update.  By unscheduling we in effect
3139         // "validate" and stop the necessary full repaint from occurring.  Basically any basic
3140         // append/remove DHTML is broken by this call.  For now, I have removed the optimization
3141         // until we have a better invalidation stategy. -dwh
3142         //v->unscheduleRelayout();
3143     }
3144 }
3145
3146 void Frame::forceLayoutWithPageWidthRange(float minPageWidth, float maxPageWidth)
3147 {
3148     // Dumping externalRepresentation(m_frame->renderer()).ascii() is a good trick to see
3149     // the state of things before and after the layout
3150     RenderView *root = static_cast<RenderView*>(document()->renderer());
3151     if (root) {
3152         // This magic is basically copied from khtmlview::print
3153         int pageW = (int)ceilf(minPageWidth);
3154         root->setWidth(pageW);
3155         root->setNeedsLayoutAndMinMaxRecalc();
3156         forceLayout();
3157         
3158         // If we don't fit in the minimum page width, we'll lay out again. If we don't fit in the
3159         // maximum page width, we will lay out to the maximum page width and clip extra content.
3160         // FIXME: We are assuming a shrink-to-fit printing implementation.  A cropping
3161         // implementation should not do this!
3162         int rightmostPos = root->rightmostPosition();
3163         if (rightmostPos > minPageWidth) {
3164             pageW = min(rightmostPos, (int)ceilf(maxPageWidth));
3165             root->setWidth(pageW);
3166             root->setNeedsLayoutAndMinMaxRecalc();
3167             forceLayout();
3168         }
3169     }
3170 }
3171
3172 void Frame::sendResizeEvent()
3173 {
3174     if (Document* doc = document())
3175         doc->dispatchWindowEvent(EventNames::resizeEvent, false, false);
3176 }
3177
3178 void Frame::sendScrollEvent()
3179 {
3180     FrameView *v = d->m_view.get();
3181     if (v) {
3182         Document *doc = document();
3183         if (!doc)
3184             return;
3185         doc->dispatchHTMLEvent(scrollEvent, true, false);
3186     }
3187 }
3188
3189 bool Frame::scrollbarsVisible()
3190 {
3191     if (!view())
3192         return false;
3193     
3194     if (view()->hScrollBarMode() == ScrollBarAlwaysOff || view()->vScrollBarMode() == ScrollBarAlwaysOff)
3195         return false;
3196     
3197     return true;
3198 }
3199
3200 void Frame::addMetaData(const String& key, const String& value)
3201 {
3202     d->m_metaData.set(key, value);
3203 }
3204
3205 // This does the same kind of work that Frame::openURL does, except it relies on the fact
3206 // that a higher level already checked that the URLs match and the scrolling is the right thing to do.
3207 void Frame::scrollToAnchor(const KURL& URL)
3208 {
3209     d->m_url = URL;
3210     started();
3211     
3212     gotoAnchor();
3213     
3214     // It's important to model this as a load that starts and immediately finishes.
3215     // Otherwise, the parent frame may think we never finished loading.
3216     d->m_bComplete = false;
3217     checkCompleted();
3218 }
3219
3220 bool Frame::closeURL()
3221 {
3222     saveDocumentState();
3223     stopLoading(true);
3224     clearUndoRedoOperations();
3225     return true;
3226 }
3227
3228 bool Frame::canMouseDownStartSelect(Node* node)
3229 {
3230     if (!node || !node->renderer())
3231         return true;
3232     
3233     // Check to see if -webkit-user-select has been set to none
3234     if (!node->renderer()->canSelect())
3235         return false;
3236     
3237     // Some controls and images can't start a select on a mouse down.
3238     for (RenderObject* curr = node->renderer(); curr; curr = curr->parent()) {
3239         if (curr->style()->userSelect() == SELECT_IGNORE)
3240             return false;
3241     }
3242     
3243     return true;
3244 }
3245
3246 void Frame::handleMouseReleaseDoubleClickEvent(const MouseEventWithHitTestResults& event)
3247 {
3248     passWidgetMouseDownEventToWidget(event, true);
3249 }
3250
3251 bool Frame::passWidgetMouseDownEventToWidget(const MouseEventWithHitTestResults& event, bool isDoubleClick)
3252 {
3253     // Figure out which view to send the event to.
3254     RenderObject *target = event.targetNode() ? event.targetNode()->renderer() : 0;
3255     if (!target)
3256         return false;
3257     
3258     Widget* widget = RenderLayer::gScrollBar;
3259     if (!widget) {
3260         if (!target->isWidget())
3261             return false;
3262         widget = static_cast<RenderWidget*>(target)->widget();
3263     }
3264     
3265     // Doubleclick events don't exist in Cocoa.  Since passWidgetMouseDownEventToWidget will
3266     // just pass _currentEvent down to the widget,  we don't want to call it for events that
3267     // don't correspond to Cocoa events.  The mousedown/ups will have already been passed on as
3268     // part of the pressed/released handling.
3269     if (!isDoubleClick)
3270         return passMouseDownEventToWidget(widget);
3271     return true;
3272 }
3273
3274 bool Frame::passWidgetMouseDownEventToWidget(RenderWidget *renderWidget)
3275 {
3276     return passMouseDownEventToWidget(renderWidget->widget());
3277 }
3278
3279 void Frame::clearTimers(FrameView *view)
3280 {
3281     if (view) {
3282         view->unscheduleRelayout();
3283         if (view->frame()) {
3284             Document* document = view->frame()->document();
3285             if (document && document->renderer() && document->renderer()->layer())
3286                 document->renderer()->layer()->suspendMarquees();
3287         }
3288     }
3289 }
3290
3291 void Frame::clearTimers()
3292 {
3293     clearTimers(d->m_view.get());
3294 }
3295
3296 RenderStyle *Frame::styleForSelectionStart(Node *&nodeToRemove) const
3297 {
3298     nodeToRemove = 0;
3299     
3300     if (!document())
3301         return 0;
3302     if (selectionController()->isNone())
3303         return 0;
3304     
3305     Position pos = selectionController()->selection().visibleStart().deepEquivalent();
3306     if (!pos.inRenderedContent())
3307         return 0;
3308     Node *node = pos.node();
3309     if (!node)
3310         return 0;
3311     
3312     if (!d->m_typingStyle)
3313         return node->renderer()->style();
3314     
3315     ExceptionCode ec = 0;
3316     RefPtr<Element> styleElement = document()->createElementNS(xhtmlNamespaceURI, "span", ec);
3317     ASSERT(ec == 0);
3318     
3319     styleElement->setAttribute(styleAttr, d->m_typingStyle->cssText().impl(), ec);
3320     ASSERT(ec == 0);
3321     
3322     styleElement->appendChild(document()->createEditingTextNode(""), ec);
3323     ASSERT(ec == 0);
3324     
3325     node->parentNode()->appendChild(styleElement, ec);
3326     ASSERT(ec == 0);
3327     
3328     nodeToRemove = styleElement.get();    
3329     return styleElement->renderer()->style();
3330 }
3331
3332 void Frame::setMediaType(const String& type)
3333 {
3334     if (d->m_view)
3335         d->m_view->setMediaType(type);
3336 }
3337
3338 void Frame::setSelectionFromNone()
3339 {
3340     // Put a caret inside the body if the entire frame is editable (either the 
3341     // entire WebView is editable or designMode is on for this document).
3342     Document *doc = document();
3343     if (!doc || !selectionController()->isNone() || !isContentEditable())
3344         return;
3345         
3346     Node* node = doc->documentElement();
3347     while (node && !node->hasTagName(bodyTag))
3348         node = node->traverseNextNode();
3349     if (node)
3350         selectionController()->setSelection(Selection(Position(node, 0), DOWNSTREAM));
3351 }
3352
3353 bool Frame::isActive() const
3354 {
3355     return d->m_isActive;
3356 }
3357
3358 void Frame::setIsActive(bool flag)
3359 {
3360     if (d->m_isActive == flag)
3361         return;
3362     
3363     d->m_isActive = flag;
3364
3365     // This method does the job of updating the view based on whether the view is "active".
3366     // This involves three kinds of drawing updates:
3367
3368     // 1. The background color used to draw behind selected content (active | inactive color)
3369     if (d->m_view)
3370         d->m_view->updateContents(enclosingIntRect(visibleSelectionRect()));
3371
3372     // 2. Caret blinking (blinks | does not blink)
3373     if (flag)
3374         setSelectionFromNone();
3375     setCaretVisible(flag);
3376     
3377     // 3. The drawing of a focus ring around links in web pages.
3378     Document *doc = document();
3379     if (doc) {
3380         Node *node = doc->focusNode();
3381         if (node) {
3382             node->setChanged();
3383             if (node->renderer() && node->renderer()->style()->hasAppearance())
3384                 theme()->stateChanged(node->renderer(), FocusState);
3385         }
3386     }
3387     
3388     // 4. Changing the tint of controls from clear to aqua/graphite and vice versa.  We
3389     // do a "fake" paint.  When the theme gets a paint call, it can then do an invalidate.  This is only
3390     // done if the theme supports control tinting.
3391     if (doc && d->m_view && theme()->supportsControlTints() && renderer()) {
3392         doc->updateLayout(); // Ensure layout is up to date.
3393         IntRect visibleRect(enclosingIntRect(d->m_view->visibleContentRect()));
3394         GraphicsContext context((PlatformGraphicsContext*)0);
3395         context.setUpdatingControlTints(true);
3396         paint(&context, visibleRect);
3397     }
3398    
3399     // 5. Enable or disable secure keyboard entry
3400     if ((flag && !isSecureKeyboardEntry() && doc && doc->focusNode() && doc->focusNode()->hasTagName(inputTag) && 
3401             static_cast<HTMLInputElement*>(doc->focusNode())->inputType() == HTMLInputElement::PASSWORD) ||
3402         (!flag && isSecureKeyboardEntry()))
3403             setSecureKeyboardEntry(flag);
3404 }
3405
3406 void Frame::setWindowHasFocus(bool flag)
3407 {
3408     if (d->m_windowHasFocus == flag)
3409         return;
3410     d->m_windowHasFocus = flag;
3411     
3412     if (Document *doc = document())
3413         doc->dispatchWindowEvent(flag ? focusEvent : blurEvent, false, false);
3414 }
3415
3416 bool Frame::inViewSourceMode() const
3417 {
3418     return d->m_inViewSourceMode;
3419 }
3420
3421 void Frame::setInViewSourceMode(bool mode) const
3422 {
3423     d->m_inViewSourceMode = mode;
3424 }
3425   
3426 UChar Frame::backslashAsCurrencySymbol() const
3427 {
3428     Document *doc = document();
3429     if (!doc)
3430         return '\\';
3431     Decoder *decoder = doc->decoder();
3432     if (!decoder)
3433         return '\\';
3434
3435     return decoder->encoding().backslashAsCurrencySymbol();
3436 }
3437
3438 bool Frame::markedTextUsesUnderlines() const
3439 {
3440     return d->m_markedTextUsesUnderlines;
3441 }
3442
3443 const Vector<MarkedTextUnderline>& Frame::markedTextUnderlines() const
3444 {
3445     return d->m_markedTextUnderlines;
3446 }
3447
3448 // Searches from the beginning of the document if nothing is selected.
3449 bool Frame::findString(const String& target, bool forward, bool caseFlag, bool wrapFlag)
3450 {
3451     if (target.isEmpty())
3452         return false;
3453     
3454     // Initially search from the start (if forward) or end (if backward) of the selection, and search to edge of document.
3455     RefPtr<Range> searchRange(rangeOfContents(document()));
3456     Selection selection(selectionController()->selection());
3457     if (!selection.isNone()) {
3458         if (forward)
3459             setStart(searchRange.get(), selection.visibleStart());
3460         else
3461             setEnd(searchRange.get(), selection.visibleEnd());
3462     }
3463     RefPtr<Range> resultRange(findPlainText(searchRange.get(), target, forward, caseFlag));
3464     // If the found range is already selected, find again.
3465     // Build a selection with the found range to remove collapsed whitespace.
3466     // Compare ranges instead of selection objects to ignore the way that the current selection was made.
3467     if (!selection.isNone() && *Selection(resultRange.get()).toRange() == *selection.toRange()) {
3468         searchRange = rangeOfContents(document());
3469         if (forward)
3470             setStart(searchRange.get(), selection.visibleEnd());
3471         else
3472             setEnd(searchRange.get(), selection.visibleStart());
3473         resultRange = findPlainText(searchRange.get(), target, forward, caseFlag);
3474     }
3475     
3476     int exception = 0;
3477     
3478     // If we didn't find anything and we're wrapping, search again in the entire document (this will
3479     // redundantly re-search the area already searched in some cases).
3480     if (resultRange->collapsed(exception) && wrapFlag) {
3481         searchRange = rangeOfContents(document());
3482         resultRange = findPlainText(searchRange.get(), target, forward, caseFlag);
3483         // We used to return false here if we ended up with the same range that we started with
3484         // (e.g., the selection was already the only instance of this text). But we decided that
3485         // this should be a success case instead, so we'll just fall through in that case.
3486     }
3487
3488     if (resultRange->collapsed(exception))
3489         return false;
3490
3491     selectionController()->setSelection(Selection(resultRange.get(), DOWNSTREAM));
3492     revealSelection();
3493     return true;
3494 }
3495
3496 unsigned Frame::markAllMatchesForText(const String& target, bool caseFlag)
3497 {
3498     if (target.isEmpty())
3499         return 0;
3500     
3501     RefPtr<Range> searchRange(rangeOfContents(document()));
3502     
3503     int exception = 0;
3504     unsigned matchCount = 0;
3505     do {
3506         RefPtr<Range> resultRange(findPlainText(searchRange.get(), target, true, caseFlag));
3507         if (resultRange->collapsed(exception))
3508             break;
3509         
3510         // A non-collapsed result range can in some funky whitespace cases still not
3511         // advance the range's start position (4509328). Break to avoid infinite loop.
3512         VisiblePosition newStart = endVisiblePosition(resultRange.get(), DOWNSTREAM);
3513         if (newStart == startVisiblePosition(searchRange.get(), DOWNSTREAM))
3514             break;
3515
3516         ++matchCount;
3517         document()->addMarker(resultRange.get(), DocumentMarker::TextMatch);        
3518         
3519         setStart(searchRange.get(), newStart);
3520     } while (true);
3521     
3522     // Do a "fake" paint in order to execute the code that computes the rendered rect for 
3523     // each text match.
3524     Document* doc = document();
3525     if (doc && d->m_view && renderer()) {
3526         doc->updateLayout(); // Ensure layout is up to date.
3527         IntRect visibleRect(enclosingIntRect(d->m_view->visibleContentRect()));
3528         GraphicsContext context((PlatformGraphicsContext*)0);
3529         context.setPaintingDisabled(true);
3530         paint(&context, visibleRect);
3531     }
3532     
3533     return matchCount;
3534 }
3535
3536 bool Frame::markedTextMatchesAreHighlighted() const
3537 {
3538     return d->m_highlightTextMatches;
3539 }
3540
3541 void Frame::setMarkedTextMatchesAreHighlighted(bool flag)
3542 {
3543     if (flag == d->m_highlightTextMatches)
3544         return;
3545     
3546     d->m_highlightTextMatches = flag;
3547     document()->repaintMarkers(DocumentMarker::TextMatch);
3548 }
3549
3550 void Frame::prepareForUserAction()
3551 {
3552     // Reset the multiple form submission protection code.
3553     // We'll let you submit the same form twice if you do two separate user actions.
3554     d->m_submittedFormURL = KURL();
3555 }
3556
3557 Node *Frame::mousePressNode()
3558 {
3559     return d->m_mousePressNode.get();
3560 }
3561
3562 bool Frame::isComplete() const
3563 {
3564     return d->m_bComplete;
3565 }
3566
3567 bool Frame::isLoadingMainResource() const
3568 {
3569     return d->m_bLoadingMainResource;
3570 }
3571
3572 FrameTree* Frame::tree() const
3573 {
3574     return &d->m_treeNode;
3575 }
3576
3577 DOMWindow* Frame::domWindow() const
3578 {
3579     if (!d->m_domWindow)
3580         d->m_domWindow = new DOMWindow(const_cast<Frame*>(this));
3581
3582     return d->m_domWindow.get();
3583 }
3584
3585 KURL Frame::url() const
3586 {
3587     return d->m_url;
3588 }
3589
3590 void Frame::startRedirectionTimer()
3591 {
3592     d->m_redirectionTimer.startOneShot(d->m_delayRedirect);
3593 }
3594
3595 void Frame::stopRedirectionTimer()
3596 {
3597     d->m_redirectionTimer.stop();
3598 }
3599
3600 void Frame::frameDetached()
3601 {
3602 }
3603
3604 void Frame::updateBaseURLForEmptyDocument()
3605 {
3606     Element* owner = ownerElement();
3607     // FIXME: Should embed be included?
3608     if (owner && (owner->hasTagName(iframeTag) || owner->hasTagName(objectTag) || owner->hasTagName(embedTag)))
3609         d->m_doc->setBaseURL(tree()->parent()->d->m_doc->baseURL());
3610 }
3611
3612 Page* Frame::page() const
3613 {
3614     return d->m_page;
3615 }
3616
3617 void Frame::pageDestroyed()
3618 {
3619     d->m_page = 0;
3620
3621     // This will stop any JS timers
3622     if (d->m_jscript && d->m_jscript->haveInterpreter())
3623         if (Window* w = Window::retrieveWindow(this))
3624             w->disconnectFrame();
3625 }
3626
3627 void Frame::completed(bool complete)
3628 {
3629     ref();
3630     for (Frame* child = tree()->firstChild(); child; child = child->tree()->nextSibling())
3631         child->parentCompleted();
3632     if (Frame* parent = tree()->parent())
3633         parent->childCompleted(complete);
3634     submitFormAgain();
3635     deref();
3636 }
3637
3638 void Frame::setStatusBarText(const String&)
3639 {
3640 }
3641
3642 void Frame::started()
3643 {
3644     for (Frame* frame = this; frame; frame = frame->tree()->parent())
3645         frame->d->m_bComplete = false;
3646 }
3647
3648 void Frame::disconnectOwnerElement()
3649 {
3650     if (d->m_ownerElement && d->m_page)
3651         d->m_page->decrementFrameCount();
3652         
3653     d->m_ownerElement = 0;
3654 }
3655
3656 String Frame::documentTypeString() const
3657 {
3658     if (Document *doc = document())
3659         if (DocumentType *doctype = doc->realDocType())
3660             return doctype->toString();
3661
3662     return String();
3663 }
3664
3665 bool Frame::containsPlugins() const 
3666
3667     return d->m_plugins.size() != 0;
3668 }
3669
3670 bool Frame::prohibitsScrolling() const
3671 {
3672     return d->m_prohibitsScrolling;
3673 }
3674
3675 void Frame::setProhibitsScrolling(const bool prohibit)
3676 {
3677     d->m_prohibitsScrolling = prohibit;
3678 }
3679
3680 } // namespace WebCore