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