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