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