1428e990a673f2c4dbe44a2c7793fe3ce79da362
[WebKit-https.git] / WebCore / page / Frame.cpp
1 /*
2  * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
3  *                     1999 Lars Knoll <knoll@kde.org>
4  *                     1999 Antti Koivisto <koivisto@kde.org>
5  *                     2000 Simon Hausmann <hausmann@kde.org>
6  *                     2000 Stefan Schimanski <1Stein@gmx.de>
7  *                     2001 George Staikos <staikos@kde.org>
8  * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
9  * Copyright (C) 2005 Alexey Proskuryakov <ap@nypop.com>
10  * Copyright (C) 2007 Trolltech ASA
11  * Copyright (C) 2008 Eric Seidel <eric@webkit.org>
12  *
13  * This library is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU Library General Public
15  * License as published by the Free Software Foundation; either
16  * version 2 of the License, or (at your option) any later version.
17  *
18  * This library is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21  * Library General Public License for more details.
22  *
23  * You should have received a copy of the GNU Library General Public License
24  * along with this library; see the file COPYING.LIB.  If not, write to
25  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
26  * Boston, MA 02110-1301, USA.
27  */
28
29 #include "config.h"
30 #include "Frame.h"
31 #include "FramePrivate.h"
32
33 #include "ApplyStyleCommand.h"
34 #include "BeforeUnloadEvent.h"
35 #include "CSSComputedStyleDeclaration.h"
36 #include "CSSProperty.h"
37 #include "CSSPropertyNames.h"
38 #include "CachedCSSStyleSheet.h"
39 #include "DOMWindow.h"
40 #include "DocLoader.h"
41 #include "DocumentType.h"
42 #include "EditingText.h"
43 #include "EditorClient.h"
44 #include "EventNames.h"
45 #include "FocusController.h"
46 #include "FrameLoader.h"
47 #include "FrameView.h"
48 #include "GraphicsContext.h"
49 #include "HTMLDocument.h"
50 #include "HTMLFormElement.h"
51 #include "HTMLFrameElementBase.h"
52 #include "HTMLFormControlElement.h"
53 #include "HTMLNames.h"
54 #include "HTMLTableCellElement.h"
55 #include "HitTestResult.h"
56 #include "JSDOMWindowShell.h"
57 #include "Logging.h"
58 #include "markup.h"
59 #include "MediaFeatureNames.h"
60 #include "Navigator.h"
61 #include "NodeList.h"
62 #include "Page.h"
63 #include "RegularExpression.h"
64 #include "RenderPart.h"
65 #include "RenderTableCell.h"
66 #include "RenderTextControl.h"
67 #include "RenderTheme.h"
68 #include "RenderView.h"
69 #include "Settings.h"
70 #include "SystemTime.h"
71 #include "TextIterator.h"
72 #include "TextResourceDecoder.h"
73 #include "XMLNames.h"
74 #include "ScriptController.h"
75 #include "npruntime_impl.h"
76 #include "runtime_root.h"
77 #include "visible_units.h"
78 #include <wtf/RefCountedLeakCounter.h>
79
80 #if FRAME_LOADS_USER_STYLESHEET
81 #include "UserStyleSheetLoader.h"
82 #endif
83
84 #if ENABLE(SVG)
85 #include "SVGDocument.h"
86 #include "SVGDocumentExtensions.h"
87 #include "SVGNames.h"
88 #include "XLinkNames.h"
89 #endif
90
91 using namespace std;
92
93 namespace WebCore {
94
95 using namespace EventNames;
96 using namespace HTMLNames;
97
98 double Frame::s_currentPaintTimeStamp = 0.0;
99
100 #ifndef NDEBUG    
101 static WTF::RefCountedLeakCounter frameCounter("Frame");
102 #endif
103
104 static inline Frame* parentFromOwnerElement(HTMLFrameOwnerElement* ownerElement)
105 {
106     if (!ownerElement)
107         return 0;
108     return ownerElement->document()->frame();
109 }
110
111 Frame::Frame(Page* page, HTMLFrameOwnerElement* ownerElement, FrameLoaderClient* frameLoaderClient) 
112     : d(new FramePrivate(page, parentFromOwnerElement(ownerElement), this, ownerElement, frameLoaderClient))
113 {
114     AtomicString::init();
115     EventNames::init();
116     HTMLNames::init();
117     QualifiedName::init();
118     MediaFeatureNames::init();
119
120 #if ENABLE(SVG)
121     SVGNames::init();
122     XLinkNames::init();
123 #endif
124
125     XMLNames::init();
126
127     if (!ownerElement)
128         page->setMainFrame(this);
129     else {
130         page->incrementFrameCount();
131         // Make sure we will not end up with two frames referencing the same owner element.
132         ASSERT((!(ownerElement->m_contentFrame)) || (ownerElement->m_contentFrame->ownerElement() != ownerElement));        
133         ownerElement->m_contentFrame = this;
134     }
135
136 #ifndef NDEBUG
137     frameCounter.increment();
138 #endif
139 }
140
141 Frame::~Frame()
142 {
143     setView(0);
144     loader()->clearRecordedFormValues();
145     loader()->cancelAndClear();
146     
147     // FIXME: We should not be doing all this work inside the destructor
148
149     ASSERT(!d->m_lifeSupportTimer.isActive());
150
151 #ifndef NDEBUG
152     frameCounter.decrement();
153 #endif
154
155     if (d->m_script.haveWindowShell())
156         d->m_script.windowShell()->disconnectFrame();
157
158     disconnectOwnerElement();
159     
160     if (d->m_domWindow)
161         d->m_domWindow->disconnectFrame();
162
163     HashSet<DOMWindow*>::iterator end = d->m_liveFormerWindows.end();
164     for (HashSet<DOMWindow*>::iterator it = d->m_liveFormerWindows.begin(); it != end; ++it)
165         (*it)->disconnectFrame();
166             
167     if (d->m_view) {
168         d->m_view->hide();
169         d->m_view->clearFrame();
170     }
171
172     ASSERT(!d->m_lifeSupportTimer.isActive());
173
174 #if FRAME_LOADS_USER_STYLESHEET
175     delete d->m_userStyleSheetLoader;
176 #endif
177
178     delete d;
179     d = 0;
180 }
181
182 void Frame::init()
183 {
184     d->m_loader.init();
185 }
186
187 FrameLoader* Frame::loader() const
188 {
189     return &d->m_loader;
190 }
191
192 FrameView* Frame::view() const
193 {
194     return d->m_view.get();
195 }
196
197 void Frame::setView(FrameView* view)
198 {
199     // Detach the document now, so any onUnload handlers get run - if
200     // we wait until the view is destroyed, then things won't be
201     // hooked up enough for some JavaScript calls to work.
202     if (!view && d->m_doc && d->m_doc->attached() && !d->m_doc->inPageCache()) {
203         // FIXME: We don't call willRemove here. Why is that OK?
204         d->m_doc->detach();
205         if (d->m_view)
206             d->m_view->unscheduleRelayout();
207     }
208     eventHandler()->clear();
209
210     d->m_view = view;
211
212     // Only one form submission is allowed per view of a part.
213     // Since this part may be getting reused as a result of being
214     // pulled from the back/forward cache, reset this flag.
215     loader()->resetMultipleFormSubmissionProtection();
216 }
217
218 ScriptController* Frame::script()
219 {
220     return &d->m_script;
221 }
222
223 Document* Frame::document() const
224 {
225     return d->m_doc.get();
226 }
227
228 void Frame::setDocument(PassRefPtr<Document> newDoc)
229 {
230     if (d->m_doc && d->m_doc->attached() && !d->m_doc->inPageCache()) {
231         // FIXME: We don't call willRemove here. Why is that OK?
232         d->m_doc->detach();
233     }
234
235     d->m_doc = newDoc;
236     if (d->m_doc && selection()->isFocusedAndActive())
237         setUseSecureKeyboardEntry(d->m_doc->useSecureKeyboardEntryWhenActive());
238         
239     if (d->m_doc && !d->m_doc->attached())
240         d->m_doc->attach();
241
242     // Update the cached 'document' property, which is now stale.
243     d->m_script.updateDocument();
244 }
245
246 Settings* Frame::settings() const
247 {
248     return d->m_page ? d->m_page->settings() : 0;
249 }
250
251 String Frame::selectedText() const
252 {
253     return plainText(selection()->toRange().get());
254 }
255
256 IntRect Frame::firstRectForRange(Range* range) const
257 {
258     int extraWidthToEndOfLine = 0;
259     ExceptionCode ec = 0;
260     ASSERT(range->startContainer(ec));
261     ASSERT(range->endContainer(ec));
262     InlineBox* startInlineBox;
263     int startCaretOffset;
264     range->startPosition().getInlineBoxAndOffset(DOWNSTREAM, startInlineBox, startCaretOffset);
265     IntRect startCaretRect = range->startContainer(ec)->renderer()->caretRect(startInlineBox, startCaretOffset, &extraWidthToEndOfLine);
266
267     InlineBox* endInlineBox;
268     int endCaretOffset;
269     range->endPosition().getInlineBoxAndOffset(UPSTREAM, endInlineBox, endCaretOffset);
270     IntRect endCaretRect = range->endContainer(ec)->renderer()->caretRect(endInlineBox, endCaretOffset);
271
272     if (startCaretRect.y() == endCaretRect.y()) {
273         // start and end are on the same line
274         return IntRect(min(startCaretRect.x(), endCaretRect.x()), 
275                        startCaretRect.y(), 
276                        abs(endCaretRect.x() - startCaretRect.x()),
277                        max(startCaretRect.height(), endCaretRect.height()));
278     }
279     
280     // start and end aren't on the same line, so go from start to the end of its line
281     return IntRect(startCaretRect.x(), 
282                    startCaretRect.y(),
283                    startCaretRect.width() + extraWidthToEndOfLine,
284                    startCaretRect.height());
285 }
286
287 SelectionController* Frame::selection() const
288 {
289     return &d->m_selectionController;
290 }
291
292 Editor* Frame::editor() const
293 {
294     return &d->m_editor;
295 }
296
297 TextGranularity Frame::selectionGranularity() const
298 {
299     return d->m_selectionGranularity;
300 }
301
302 void Frame::setSelectionGranularity(TextGranularity granularity) const
303 {
304     d->m_selectionGranularity = granularity;
305 }
306
307 SelectionController* Frame::dragCaretController() const
308 {
309     return d->m_page->dragCaretController();
310 }
311
312
313 AnimationController* Frame::animation() const
314 {
315     return &d->m_animationController;
316 }
317
318 static RegularExpression* createRegExpForLabels(const Vector<String>& labels)
319 {
320     // REVIEW- version of this call in FrameMac.mm caches based on the NSArray ptrs being
321     // the same across calls.  We can't do that.
322
323     static RegularExpression wordRegExp = RegularExpression("\\w");
324     String pattern("(");
325     unsigned int numLabels = labels.size();
326     unsigned int i;
327     for (i = 0; i < numLabels; i++) {
328         String label = labels[i];
329
330         bool startsWithWordChar = false;
331         bool endsWithWordChar = false;
332         if (label.length() != 0) {
333             startsWithWordChar = wordRegExp.search(label.substring(0, 1)) >= 0;
334             endsWithWordChar = wordRegExp.search(label.substring(label.length() - 1, 1)) >= 0;
335         }
336         
337         if (i != 0)
338             pattern.append("|");
339         // Search for word boundaries only if label starts/ends with "word characters".
340         // If we always searched for word boundaries, this wouldn't work for languages
341         // such as Japanese.
342         if (startsWithWordChar) {
343             pattern.append("\\b");
344         }
345         pattern.append(label);
346         if (endsWithWordChar) {
347             pattern.append("\\b");
348         }
349     }
350     pattern.append(")");
351     return new RegularExpression(pattern, false);
352 }
353
354 String Frame::searchForLabelsAboveCell(RegularExpression* regExp, HTMLTableCellElement* cell)
355 {
356     RenderTableCell* cellRenderer = static_cast<RenderTableCell*>(cell->renderer());
357
358     if (cellRenderer && cellRenderer->isTableCell()) {
359         RenderTableCell* cellAboveRenderer = cellRenderer->table()->cellAbove(cellRenderer);
360
361         if (cellAboveRenderer) {
362             HTMLTableCellElement* aboveCell =
363                 static_cast<HTMLTableCellElement*>(cellAboveRenderer->element());
364
365             if (aboveCell) {
366                 // search within the above cell we found for a match
367                 for (Node* n = aboveCell->firstChild(); n; n = n->traverseNextNode(aboveCell)) {
368                     if (n->isTextNode() && n->renderer() && n->renderer()->style()->visibility() == VISIBLE) {
369                         // For each text chunk, run the regexp
370                         String nodeString = n->nodeValue();
371                         int pos = regExp->searchRev(nodeString);
372                         if (pos >= 0)
373                             return nodeString.substring(pos, regExp->matchedLength());
374                     }
375                 }
376             }
377         }
378     }
379     // Any reason in practice to search all cells in that are above cell?
380     return String();
381 }
382
383 String Frame::searchForLabelsBeforeElement(const Vector<String>& labels, Element* element)
384 {
385     OwnPtr<RegularExpression> regExp(createRegExpForLabels(labels));
386     // We stop searching after we've seen this many chars
387     const unsigned int charsSearchedThreshold = 500;
388     // This is the absolute max we search.  We allow a little more slop than
389     // charsSearchedThreshold, to make it more likely that we'll search whole nodes.
390     const unsigned int maxCharsSearched = 600;
391     // If the starting element is within a table, the cell that contains it
392     HTMLTableCellElement* startingTableCell = 0;
393     bool searchedCellAbove = false;
394
395     // walk backwards in the node tree, until another element, or form, or end of tree
396     int unsigned lengthSearched = 0;
397     Node* n;
398     for (n = element->traversePreviousNode();
399          n && lengthSearched < charsSearchedThreshold;
400          n = n->traversePreviousNode())
401     {
402         if (n->hasTagName(formTag)
403             || (n->isHTMLElement()
404                 && static_cast<HTMLElement*>(n)->isGenericFormElement()))
405         {
406             // We hit another form element or the start of the form - bail out
407             break;
408         } else if (n->hasTagName(tdTag) && !startingTableCell) {
409             startingTableCell = static_cast<HTMLTableCellElement*>(n);
410         } else if (n->hasTagName(trTag) && startingTableCell) {
411             String result = searchForLabelsAboveCell(regExp.get(), startingTableCell);
412             if (!result.isEmpty())
413                 return result;
414             searchedCellAbove = true;
415         } else if (n->isTextNode() && n->renderer() && n->renderer()->style()->visibility() == VISIBLE) {
416             // For each text chunk, run the regexp
417             String nodeString = n->nodeValue();
418             // add 100 for slop, to make it more likely that we'll search whole nodes
419             if (lengthSearched + nodeString.length() > maxCharsSearched)
420                 nodeString = nodeString.right(charsSearchedThreshold - lengthSearched);
421             int pos = regExp->searchRev(nodeString);
422             if (pos >= 0)
423                 return nodeString.substring(pos, regExp->matchedLength());
424             lengthSearched += nodeString.length();
425         }
426     }
427
428     // If we started in a cell, but bailed because we found the start of the form or the
429     // previous element, we still might need to search the row above us for a label.
430     if (startingTableCell && !searchedCellAbove) {
431          return searchForLabelsAboveCell(regExp.get(), startingTableCell);
432     }
433     return String();
434 }
435
436 String Frame::matchLabelsAgainstElement(const Vector<String>& labels, Element* element)
437 {
438     String name = element->getAttribute(nameAttr);
439     if (name.isEmpty())
440         return String();
441
442     // Make numbers and _'s in field names behave like word boundaries, e.g., "address2"
443     replace(name, RegularExpression("\\d"), " ");
444     name.replace('_', ' ');
445     
446     OwnPtr<RegularExpression> regExp(createRegExpForLabels(labels));
447     // Use the largest match we can find in the whole name string
448     int pos;
449     int length;
450     int bestPos = -1;
451     int bestLength = -1;
452     int start = 0;
453     do {
454         pos = regExp->search(name, start);
455         if (pos != -1) {
456             length = regExp->matchedLength();
457             if (length >= bestLength) {
458                 bestPos = pos;
459                 bestLength = length;
460             }
461             start = pos + 1;
462         }
463     } while (pos != -1);
464
465     if (bestPos != -1)
466         return name.substring(bestPos, bestLength);
467     return String();
468 }
469
470 const Selection& Frame::mark() const
471 {
472     return d->m_mark;
473 }
474
475 void Frame::setMark(const Selection& s)
476 {
477     ASSERT(!s.base().node() || s.base().node()->document() == document());
478     ASSERT(!s.extent().node() || s.extent().node()->document() == document());
479     ASSERT(!s.start().node() || s.start().node()->document() == document());
480     ASSERT(!s.end().node() || s.end().node()->document() == document());
481
482     d->m_mark = s;
483 }
484
485 void Frame::notifyRendererOfSelectionChange(bool userTriggered)
486 {
487     RenderObject* renderer = 0;
488     if (selection()->rootEditableElement())
489         renderer = selection()->rootEditableElement()->shadowAncestorNode()->renderer();
490
491     // If the current selection is in a textfield or textarea, notify the renderer that the selection has changed
492     if (renderer && (renderer->isTextArea() || renderer->isTextField()))
493         static_cast<RenderTextControl*>(renderer)->selectionChanged(userTriggered);
494 }
495
496 void Frame::invalidateSelection()
497 {
498     selection()->setNeedsLayout();
499     selectionLayoutChanged();
500 }
501
502 void Frame::setCaretVisible(bool flag)
503 {
504     if (d->m_caretVisible == flag)
505         return;
506     clearCaretRectIfNeeded();
507     d->m_caretVisible = flag;
508     selectionLayoutChanged();
509 }
510
511 void Frame::clearCaretRectIfNeeded()
512 {
513     if (d->m_caretPaint) {
514         d->m_caretPaint = false;
515         selection()->invalidateCaretRect();
516     }
517 }
518
519 // Helper function that tells whether a particular node is an element that has an entire
520 // Frame and FrameView, a <frame>, <iframe>, or <object>.
521 static bool isFrameElement(const Node *n)
522 {
523     if (!n)
524         return false;
525     RenderObject *renderer = n->renderer();
526     if (!renderer || !renderer->isWidget())
527         return false;
528     Widget* widget = static_cast<RenderWidget*>(renderer)->widget();
529     return widget && widget->isFrameView();
530 }
531
532 void Frame::setFocusedNodeIfNeeded()
533 {
534     if (!document() || selection()->isNone() || !selection()->isFocusedAndActive())
535         return;
536
537     Node* target = selection()->rootEditableElement();
538     if (target) {
539         RenderObject* renderer = target->renderer();
540
541         // Walk up the render tree to search for a node to focus.
542         // Walking up the DOM tree wouldn't work for shadow trees, like those behind the engine-based text fields.
543         while (renderer) {
544             // We don't want to set focus on a subframe when selecting in a parent frame,
545             // so add the !isFrameElement check here. There's probably a better way to make this
546             // work in the long term, but this is the safest fix at this time.
547             if (target && target->isMouseFocusable() && !isFrameElement(target)) {
548                 page()->focusController()->setFocusedNode(target, this);
549                 return;
550             }
551             renderer = renderer->parent();
552             if (renderer)
553                 target = renderer->element();
554         }
555         document()->setFocusedNode(0);
556     }
557 }
558
559 void Frame::selectionLayoutChanged()
560 {
561     bool caretRectChanged = selection()->recomputeCaretRect();
562
563     bool shouldBlink = d->m_caretVisible
564         && selection()->isCaret() && selection()->isContentEditable();
565
566     // If the caret moved, stop the blink timer so we can restart with a
567     // black caret in the new location.
568     if (caretRectChanged || !shouldBlink)
569         d->m_caretBlinkTimer.stop();
570
571     // Start blinking with a black caret. Be sure not to restart if we're
572     // already blinking in the right location.
573     if (shouldBlink && !d->m_caretBlinkTimer.isActive()) {
574         d->m_caretBlinkTimer.startRepeating(theme()->caretBlinkFrequency());
575         if (!d->m_caretPaint) {
576             d->m_caretPaint = true;
577             selection()->invalidateCaretRect();
578         }
579     }
580
581     RenderView* canvas = contentRenderer();
582     if (!canvas)
583         return;
584
585     Selection selection = this->selection()->selection();
586         
587     if (!selection.isRange())
588         canvas->clearSelection();
589     else {
590         // Use the rightmost candidate for the start of the selection, and the leftmost candidate for the end of the selection.
591         // Example: foo <a>bar</a>.  Imagine that a line wrap occurs after 'foo', and that 'bar' is selected.   If we pass [foo, 3]
592         // as the start of the selection, the selection painting code will think that content on the line containing 'foo' is selected
593         // and will fill the gap before 'bar'.
594         Position startPos = selection.start();
595         if (startPos.downstream().isCandidate())
596             startPos = startPos.downstream();
597         Position endPos = selection.end();
598         if (endPos.upstream().isCandidate())
599             endPos = endPos.upstream();
600         
601         // We can get into a state where the selection endpoints map to the same VisiblePosition when a selection is deleted
602         // because we don't yet notify the SelectionController of text removal.
603         if (startPos.isNotNull() && endPos.isNotNull() && selection.visibleStart() != selection.visibleEnd()) {
604             RenderObject *startRenderer = startPos.node()->renderer();
605             RenderObject *endRenderer = endPos.node()->renderer();
606             canvas->setSelection(startRenderer, startPos.offset(), endRenderer, endPos.offset());
607         }
608     }
609 }
610
611 void Frame::caretBlinkTimerFired(Timer<Frame>*)
612 {
613     ASSERT(d->m_caretVisible);
614     ASSERT(selection()->isCaret());
615     bool caretPaint = d->m_caretPaint;
616     if (selection()->isCaretBlinkingSuspended() && caretPaint)
617         return;
618     d->m_caretPaint = !caretPaint;
619     selection()->invalidateCaretRect();
620 }
621
622 void Frame::paintCaret(GraphicsContext* p, const IntRect& rect) const
623 {
624     if (d->m_caretPaint && d->m_caretVisible)
625         selection()->paintCaret(p, rect);
626 }
627
628 void Frame::paintDragCaret(GraphicsContext* p, const IntRect& rect) const
629 {
630     SelectionController* dragCaretController = d->m_page->dragCaretController();
631     ASSERT(dragCaretController->selection().isCaret());
632     if (dragCaretController->selection().start().node()->document()->frame() == this)
633         dragCaretController->paintCaret(p, rect);
634 }
635
636 float Frame::zoomFactor() const
637 {
638     return d->m_zoomFactor;
639 }
640
641 bool Frame::isZoomFactorTextOnly() const
642 {
643     return d->m_page->settings()->zoomsTextOnly();
644 }
645
646 bool Frame::shouldApplyTextZoom() const
647 {
648     if (d->m_zoomFactor == 1.0f || !isZoomFactorTextOnly())
649         return false;
650 #if ENABLE(SVG)
651     if (d->m_doc && d->m_doc->isSVGDocument())
652         return false;
653 #endif
654     return true;
655 }
656
657 bool Frame::shouldApplyPageZoom() const
658 {
659     if (d->m_zoomFactor == 1.0f || isZoomFactorTextOnly())
660         return false;
661 #if ENABLE(SVG)
662     if (d->m_doc && d->m_doc->isSVGDocument())
663         return false;
664 #endif
665     return true;
666 }
667
668 void Frame::setZoomFactor(float percent, bool isTextOnly)
669 {  
670     if (d->m_zoomFactor == percent && isZoomFactorTextOnly())
671         return;
672
673 #if ENABLE(SVG)
674     // SVG doesn't care if the zoom factor is text only.  It will always apply a 
675     // zoom to the whole SVG.
676     if (d->m_doc && d->m_doc->isSVGDocument()) {
677         if (!static_cast<SVGDocument*>(d->m_doc.get())->zoomAndPanEnabled())
678             return;
679         d->m_zoomFactor = percent;
680         d->m_page->settings()->setZoomsTextOnly(true); // We do this to avoid doing any scaling of CSS pixels, since the SVG has its own notion of zoom.
681         if (d->m_doc->renderer())
682             d->m_doc->renderer()->repaint();
683         return;
684     }
685 #endif
686
687     d->m_zoomFactor = percent;
688     d->m_page->settings()->setZoomsTextOnly(isTextOnly);
689
690     if (d->m_doc)
691         d->m_doc->recalcStyle(Node::Force);
692
693     for (Frame* child = tree()->firstChild(); child; child = child->tree()->nextSibling())
694         child->setZoomFactor(d->m_zoomFactor, isTextOnly);
695
696     if (d->m_doc && d->m_doc->renderer() && d->m_doc->renderer()->needsLayout() && view()->didFirstLayout())
697         view()->layout();
698 }
699
700 void Frame::setPrinting(bool printing, float minPageWidth, float maxPageWidth, bool adjustViewSize)
701 {
702     if (!d->m_doc)
703         return;
704
705     d->m_doc->setPrinting(printing);
706     view()->setMediaType(printing ? "print" : "screen");
707     d->m_doc->updateStyleSelector();
708     forceLayoutWithPageWidthRange(minPageWidth, maxPageWidth, adjustViewSize);
709
710     for (Frame* child = tree()->firstChild(); child; child = child->tree()->nextSibling())
711         child->setPrinting(printing, minPageWidth, maxPageWidth, adjustViewSize);
712 }
713
714 void Frame::setJSStatusBarText(const String& text)
715 {
716     d->m_kjsStatusBarText = text;
717     if (d->m_page)
718         d->m_page->chrome()->setStatusbarText(this, d->m_kjsStatusBarText);
719 }
720
721 void Frame::setJSDefaultStatusBarText(const String& text)
722 {
723     d->m_kjsDefaultStatusBarText = text;
724     if (d->m_page)
725         d->m_page->chrome()->setStatusbarText(this, d->m_kjsDefaultStatusBarText);
726 }
727
728 String Frame::jsStatusBarText() const
729 {
730     return d->m_kjsStatusBarText;
731 }
732
733 String Frame::jsDefaultStatusBarText() const
734 {
735    return d->m_kjsDefaultStatusBarText;
736 }
737
738 void Frame::setNeedsReapplyStyles()
739 {
740     if (d->m_needsReapplyStyles)
741         return;
742
743     d->m_needsReapplyStyles = true;
744
745     // Invalidate the FrameView so that FrameView::layout will get called,
746     // which calls reapplyStyles.
747     view()->invalidate();
748 }
749
750 bool Frame::needsReapplyStyles() const
751 {
752     return d->m_needsReapplyStyles;
753 }
754
755 void Frame::reapplyStyles()
756 {
757     d->m_needsReapplyStyles = false;
758
759     // FIXME: This call doesn't really make sense in a method called
760     // "reapplyStyles". We should probably eventually move it into its own
761     // method.
762     if (d->m_doc)
763         d->m_doc->docLoader()->setAutoLoadImages(d->m_page && d->m_page->settings()->loadsImagesAutomatically());
764         
765 #if FRAME_LOADS_USER_STYLESHEET
766     const KURL userStyleSheetLocation = d->m_page ? d->m_page->settings()->userStyleSheetLocation() : KURL();
767     if (!userStyleSheetLocation.isEmpty())
768         setUserStyleSheetLocation(userStyleSheetLocation);
769     else
770         setUserStyleSheet(String());
771 #endif
772
773     // FIXME: It's not entirely clear why the following is needed.
774     // The document automatically does this as required when you set the style sheet.
775     // But we had problems when this code was removed. Details are in
776     // <http://bugs.webkit.org/show_bug.cgi?id=8079>.
777     if (d->m_doc)
778         d->m_doc->updateStyleSelector();
779 }
780
781 bool Frame::shouldChangeSelection(const Selection& newSelection) const
782 {
783     return shouldChangeSelection(selection()->selection(), newSelection, newSelection.affinity(), false);
784 }
785
786 bool Frame::shouldChangeSelection(const Selection& oldSelection, const Selection& newSelection, EAffinity affinity, bool stillSelecting) const
787 {
788     return editor()->client()->shouldChangeSelectedRange(oldSelection.toRange().get(), newSelection.toRange().get(),
789                                                          affinity, stillSelecting);
790 }
791
792 bool Frame::shouldDeleteSelection(const Selection& selection) const
793 {
794     return editor()->client()->shouldDeleteRange(selection.toRange().get());
795 }
796
797 bool Frame::isContentEditable() const 
798 {
799     if (d->m_editor.clientIsEditable())
800         return true;
801     if (!d->m_doc)
802         return false;
803     return d->m_doc->inDesignMode();
804 }
805
806 #if !PLATFORM(MAC)
807
808 void Frame::setUseSecureKeyboardEntry(bool)
809 {
810 }
811
812 #endif
813
814 void Frame::updateSecureKeyboardEntryIfActive()
815 {
816     if (selection()->isFocusedAndActive())
817         setUseSecureKeyboardEntry(d->m_doc->useSecureKeyboardEntryWhenActive());
818 }
819
820 CSSMutableStyleDeclaration *Frame::typingStyle() const
821 {
822     return d->m_typingStyle.get();
823 }
824
825 void Frame::setTypingStyle(CSSMutableStyleDeclaration *style)
826 {
827     d->m_typingStyle = style;
828 }
829
830 void Frame::clearTypingStyle()
831 {
832     d->m_typingStyle = 0;
833 }
834
835 void Frame::computeAndSetTypingStyle(CSSStyleDeclaration *style, EditAction editingAction)
836 {
837     if (!style || style->length() == 0) {
838         clearTypingStyle();
839         return;
840     }
841
842     // Calculate the current typing style.
843     RefPtr<CSSMutableStyleDeclaration> mutableStyle = style->makeMutable();
844     if (typingStyle()) {
845         typingStyle()->merge(mutableStyle.get());
846         mutableStyle = typingStyle();
847     }
848
849     Node* node = selection()->selection().visibleStart().deepEquivalent().node();
850     computedStyle(node)->diff(mutableStyle.get());
851     
852     // Handle block styles, substracting these from the typing style.
853     RefPtr<CSSMutableStyleDeclaration> blockStyle = mutableStyle->copyBlockProperties();
854     blockStyle->diff(mutableStyle.get());
855     if (document() && blockStyle->length() > 0)
856         applyCommand(ApplyStyleCommand::create(document(), blockStyle.get(), editingAction));
857     
858     // Set the remaining style as the typing style.
859     d->m_typingStyle = mutableStyle.release();
860 }
861
862 String Frame::selectionStartStylePropertyValue(int stylePropertyID) const
863 {
864     Node *nodeToRemove;
865     RefPtr<CSSStyleDeclaration> selectionStyle = selectionComputedStyle(nodeToRemove);
866     if (!selectionStyle)
867         return String();
868
869     String value = selectionStyle->getPropertyValue(stylePropertyID);
870
871     if (nodeToRemove) {
872         ExceptionCode ec = 0;
873         nodeToRemove->remove(ec);
874         ASSERT(ec == 0);
875     }
876
877     return value;
878 }
879
880 PassRefPtr<CSSComputedStyleDeclaration> Frame::selectionComputedStyle(Node*& nodeToRemove) const
881 {
882     nodeToRemove = 0;
883
884     if (!document())
885         return 0;
886
887     if (selection()->isNone())
888         return 0;
889
890     RefPtr<Range> range(selection()->toRange());
891     Position pos = range->editingStartPosition();
892
893     Element *elem = pos.element();
894     if (!elem)
895         return 0;
896     
897     RefPtr<Element> styleElement = elem;
898     ExceptionCode ec = 0;
899
900     if (d->m_typingStyle) {
901         styleElement = document()->createElementNS(xhtmlNamespaceURI, "span", ec);
902         ASSERT(ec == 0);
903
904         styleElement->setAttribute(styleAttr, d->m_typingStyle->cssText().impl(), ec);
905         ASSERT(ec == 0);
906         
907         styleElement->appendChild(document()->createEditingTextNode(""), ec);
908         ASSERT(ec == 0);
909
910         if (elem->renderer() && elem->renderer()->canHaveChildren()) {
911             elem->appendChild(styleElement, ec);
912         } else {
913             Node *parent = elem->parent();
914             Node *next = elem->nextSibling();
915
916             if (next) {
917                 parent->insertBefore(styleElement, next, ec);
918             } else {
919                 parent->appendChild(styleElement, ec);
920             }
921         }
922         ASSERT(ec == 0);
923
924         nodeToRemove = styleElement.get();
925     }
926
927     return computedStyle(styleElement.release());
928 }
929
930 void Frame::textFieldDidBeginEditing(Element* e)
931 {
932     if (editor()->client())
933         editor()->client()->textFieldDidBeginEditing(e);
934 }
935
936 void Frame::textFieldDidEndEditing(Element* e)
937 {
938     if (editor()->client())
939         editor()->client()->textFieldDidEndEditing(e);
940 }
941
942 void Frame::textDidChangeInTextField(Element* e)
943 {
944     if (editor()->client())
945         editor()->client()->textDidChangeInTextField(e);
946 }
947
948 bool Frame::doTextFieldCommandFromEvent(Element* e, KeyboardEvent* ke)
949 {
950     if (editor()->client())
951         return editor()->client()->doTextFieldCommandFromEvent(e, ke);
952
953     return false;
954 }
955
956 void Frame::textWillBeDeletedInTextField(Element* input)
957 {
958     if (editor()->client())
959         editor()->client()->textWillBeDeletedInTextField(input);
960 }
961
962 void Frame::textDidChangeInTextArea(Element* e)
963 {
964     if (editor()->client())
965         editor()->client()->textDidChangeInTextArea(e);
966 }
967
968 void Frame::applyEditingStyleToBodyElement() const
969 {
970     if (!d->m_doc)
971         return;
972         
973     RefPtr<NodeList> list = d->m_doc->getElementsByTagName("body");
974     unsigned len = list->length();
975     for (unsigned i = 0; i < len; i++) {
976         applyEditingStyleToElement(static_cast<Element*>(list->item(i)));    
977     }
978 }
979
980 void Frame::removeEditingStyleFromBodyElement() const
981 {
982     if (!d->m_doc)
983         return;
984         
985     RefPtr<NodeList> list = d->m_doc->getElementsByTagName("body");
986     unsigned len = list->length();
987     for (unsigned i = 0; i < len; i++) {
988         removeEditingStyleFromElement(static_cast<Element*>(list->item(i)));    
989     }
990 }
991
992 void Frame::applyEditingStyleToElement(Element* element) const
993 {
994     if (!element)
995         return;
996
997     CSSStyleDeclaration* style = element->style();
998     ASSERT(style);
999
1000     ExceptionCode ec = 0;
1001     style->setProperty(CSSPropertyWordWrap, "break-word", false, ec);
1002     ASSERT(ec == 0);
1003     style->setProperty(CSSPropertyWebkitNbspMode, "space", false, ec);
1004     ASSERT(ec == 0);
1005     style->setProperty(CSSPropertyWebkitLineBreak, "after-white-space", false, ec);
1006     ASSERT(ec == 0);
1007 }
1008
1009 void Frame::removeEditingStyleFromElement(Element*) const
1010 {
1011 }
1012
1013 #ifndef NDEBUG
1014 static HashSet<Frame*>& keepAliveSet()
1015 {
1016     static HashSet<Frame*> staticKeepAliveSet;
1017     return staticKeepAliveSet;
1018 }
1019 #endif
1020
1021 void Frame::keepAlive()
1022 {
1023     if (d->m_lifeSupportTimer.isActive())
1024         return;
1025 #ifndef NDEBUG
1026     keepAliveSet().add(this);
1027 #endif
1028     ref();
1029     d->m_lifeSupportTimer.startOneShot(0);
1030 }
1031
1032 #ifndef NDEBUG
1033 void Frame::cancelAllKeepAlive()
1034 {
1035     HashSet<Frame*>::iterator end = keepAliveSet().end();
1036     for (HashSet<Frame*>::iterator it = keepAliveSet().begin(); it != end; ++it) {
1037         Frame* frame = *it;
1038         frame->d->m_lifeSupportTimer.stop();
1039         frame->deref();
1040     }
1041     keepAliveSet().clear();
1042 }
1043 #endif
1044
1045 void Frame::lifeSupportTimerFired(Timer<Frame>*)
1046 {
1047 #ifndef NDEBUG
1048     keepAliveSet().remove(this);
1049 #endif
1050     deref();
1051 }
1052
1053 void Frame::clearDOMWindow()
1054 {
1055     if (d->m_domWindow) {
1056         d->m_liveFormerWindows.add(d->m_domWindow.get());
1057         d->m_domWindow->clear();
1058     }
1059     d->m_domWindow = 0;
1060 }
1061
1062 RenderView* Frame::contentRenderer() const
1063 {
1064     Document* doc = document();
1065     if (!doc)
1066         return 0;
1067     RenderObject* object = doc->renderer();
1068     if (!object)
1069         return 0;
1070     ASSERT(object->isRenderView());
1071     return static_cast<RenderView*>(object);
1072 }
1073
1074 HTMLFrameOwnerElement* Frame::ownerElement() const
1075 {
1076     return d->m_ownerElement;
1077 }
1078
1079 RenderPart* Frame::ownerRenderer() const
1080 {
1081     HTMLFrameOwnerElement* ownerElement = d->m_ownerElement;
1082     if (!ownerElement)
1083         return 0;
1084     RenderObject* object = ownerElement->renderer();
1085     if (!object)
1086         return 0;
1087     // FIXME: If <object> is ever fixed to disassociate itself from frames
1088     // that it has started but canceled, then this can turn into an ASSERT
1089     // since d->m_ownerElement would be 0 when the load is canceled.
1090     // https://bugs.webkit.org/show_bug.cgi?id=18585
1091     if (!object->isRenderPart())
1092         return 0;
1093     return static_cast<RenderPart*>(object);
1094 }
1095
1096 bool Frame::isDisconnected() const
1097 {
1098     return d->m_isDisconnected;
1099 }
1100
1101 void Frame::setIsDisconnected(bool isDisconnected)
1102 {
1103     d->m_isDisconnected = isDisconnected;
1104 }
1105
1106 bool Frame::excludeFromTextSearch() const
1107 {
1108     return d->m_excludeFromTextSearch;
1109 }
1110
1111 void Frame::setExcludeFromTextSearch(bool exclude)
1112 {
1113     d->m_excludeFromTextSearch = exclude;
1114 }
1115
1116 // returns FloatRect because going through IntRect would truncate any floats
1117 FloatRect Frame::selectionRect(bool clipToVisibleContent) const
1118 {
1119     RenderView* root = contentRenderer();
1120     if (!root)
1121         return IntRect();
1122     
1123     IntRect selectionRect = root->selectionRect(clipToVisibleContent);
1124     return clipToVisibleContent ? intersection(selectionRect, d->m_view->visibleContentRect()) : selectionRect;
1125 }
1126
1127 void Frame::selectionTextRects(Vector<FloatRect>& rects, bool clipToVisibleContent) const
1128 {
1129     RenderView* root = contentRenderer();
1130     if (!root)
1131         return;
1132
1133     RefPtr<Range> selectedRange = selection()->toRange();
1134
1135     Vector<IntRect> intRects;
1136     selectedRange->addLineBoxRects(intRects, true);
1137
1138     unsigned size = intRects.size();
1139     FloatRect visibleContentRect = d->m_view->visibleContentRect();
1140     for (unsigned i = 0; i < size; ++i)
1141         if (clipToVisibleContent)
1142             rects.append(intersection(intRects[i], visibleContentRect));
1143         else
1144             rects.append(intRects[i]);
1145 }
1146
1147
1148 bool Frame::isFrameSet() const
1149 {
1150     Document* document = d->m_doc.get();
1151     if (!document || !document->isHTMLDocument())
1152         return false;
1153     Node *body = static_cast<HTMLDocument*>(document)->body();
1154     return body && body->renderer() && body->hasTagName(framesetTag);
1155 }
1156
1157 // Scans logically forward from "start", including any child frames
1158 static HTMLFormElement *scanForForm(Node *start)
1159 {
1160     Node *n;
1161     for (n = start; n; n = n->traverseNextNode()) {
1162         if (n->hasTagName(formTag))
1163             return static_cast<HTMLFormElement*>(n);
1164         else if (n->isHTMLElement() && static_cast<HTMLElement*>(n)->isGenericFormElement())
1165             return static_cast<HTMLFormControlElement*>(n)->form();
1166         else if (n->hasTagName(frameTag) || n->hasTagName(iframeTag)) {
1167             Node *childDoc = static_cast<HTMLFrameElementBase*>(n)->contentDocument();
1168             if (HTMLFormElement *frameResult = scanForForm(childDoc))
1169                 return frameResult;
1170         }
1171     }
1172     return 0;
1173 }
1174
1175 // We look for either the form containing the current focus, or for one immediately after it
1176 HTMLFormElement *Frame::currentForm() const
1177 {
1178     // start looking either at the active (first responder) node, or where the selection is
1179     Node *start = d->m_doc ? d->m_doc->focusedNode() : 0;
1180     if (!start)
1181         start = selection()->start().node();
1182     
1183     // try walking up the node tree to find a form element
1184     Node *n;
1185     for (n = start; n; n = n->parentNode()) {
1186         if (n->hasTagName(formTag))
1187             return static_cast<HTMLFormElement*>(n);
1188         else if (n->isHTMLElement()
1189                    && static_cast<HTMLElement*>(n)->isGenericFormElement())
1190             return static_cast<HTMLFormControlElement*>(n)->form();
1191     }
1192     
1193     // try walking forward in the node tree to find a form element
1194     return start ? scanForForm(start) : 0;
1195 }
1196
1197 // FIXME: should this go in SelectionController?
1198 void Frame::revealSelection(const RenderLayer::ScrollAlignment& alignment) const
1199 {
1200     IntRect rect;
1201     
1202     switch (selection()->state()) {
1203         case Selection::NONE:
1204             return;
1205             
1206         case Selection::CARET:
1207             rect = selection()->caretRect();
1208             break;
1209             
1210         case Selection::RANGE:
1211             rect = enclosingIntRect(selectionRect(false));
1212             break;
1213     }
1214
1215     Position start = selection()->start();
1216
1217     ASSERT(start.node());
1218     if (start.node() && start.node()->renderer()) {
1219         // FIXME: This code only handles scrolling the startContainer's layer, but
1220         // the selection rect could intersect more than just that. 
1221         // See <rdar://problem/4799899>.
1222         if (RenderLayer *layer = start.node()->renderer()->enclosingLayer())
1223             layer->scrollRectToVisible(rect, false, alignment, alignment);
1224     }
1225 }
1226
1227 void Frame::revealCaret(const RenderLayer::ScrollAlignment& alignment) const
1228 {
1229     if (selection()->isNone())
1230         return;
1231
1232     Position extent = selection()->extent();
1233     if (extent.node() && extent.node()->renderer()) {
1234         IntRect extentRect = VisiblePosition(extent).caretRect();
1235         RenderLayer* layer = extent.node()->renderer()->enclosingLayer();
1236         if (layer)
1237             layer->scrollRectToVisible(extentRect, false, alignment, alignment);
1238     }
1239 }
1240
1241 // FIXME: why is this here instead of on the FrameView?
1242 void Frame::paint(GraphicsContext* p, const IntRect& rect)
1243 {
1244 #ifndef NDEBUG
1245     bool fillWithRed;
1246     if (!document() || document()->printing())
1247         fillWithRed = false; // Printing, don't fill with red (can't remember why).
1248     else if (document()->ownerElement())
1249         fillWithRed = false; // Subframe, don't fill with red.
1250     else if (view() && view()->isTransparent())
1251         fillWithRed = false; // Transparent, don't fill with red.
1252     else if (d->m_paintRestriction == PaintRestrictionSelectionOnly || d->m_paintRestriction == PaintRestrictionSelectionOnlyBlackText)
1253         fillWithRed = false; // Selections are transparent, don't fill with red.
1254     else if (d->m_elementToDraw)
1255         fillWithRed = false; // Element images are transparent, don't fill with red.
1256     else
1257         fillWithRed = true;
1258     
1259     if (fillWithRed)
1260         p->fillRect(rect, Color(0xFF, 0, 0));
1261 #endif
1262
1263     bool isTopLevelPainter = !s_currentPaintTimeStamp;
1264     if (isTopLevelPainter)
1265         s_currentPaintTimeStamp = currentTime();
1266     
1267     if (contentRenderer()) {
1268         ASSERT(d->m_view && !d->m_view->needsLayout());
1269         ASSERT(!d->m_isPainting);
1270         
1271         d->m_isPainting = true;
1272         
1273         // d->m_elementToDraw is used to draw only one element
1274         RenderObject* eltRenderer = d->m_elementToDraw ? d->m_elementToDraw->renderer() : 0;
1275         if (d->m_paintRestriction == PaintRestrictionNone)
1276             document()->invalidateRenderedRectsForMarkersInRect(rect);
1277         contentRenderer()->layer()->paint(p, rect, d->m_paintRestriction, eltRenderer);
1278         
1279         d->m_isPainting = false;
1280
1281 #if ENABLE(DASHBOARD_SUPPORT)
1282         // Regions may have changed as a result of the visibility/z-index of element changing.
1283         if (document()->dashboardRegionsDirty())
1284             view()->updateDashboardRegions();
1285 #endif
1286     } else
1287         LOG_ERROR("called Frame::paint with nil renderer");
1288         
1289     if (isTopLevelPainter)
1290         s_currentPaintTimeStamp = 0;
1291 }
1292
1293 void Frame::setPaintRestriction(PaintRestriction pr)
1294 {
1295     d->m_paintRestriction = pr;
1296 }
1297     
1298 bool Frame::isPainting() const
1299 {
1300     return d->m_isPainting;
1301 }
1302
1303 void Frame::adjustPageHeight(float *newBottom, float oldTop, float oldBottom, float bottomLimit)
1304 {
1305     RenderView* root = contentRenderer();
1306     if (root) {
1307         // Use a context with painting disabled.
1308         GraphicsContext context((PlatformGraphicsContext*)0);
1309         root->setTruncatedAt((int)floorf(oldBottom));
1310         IntRect dirtyRect(0, (int)floorf(oldTop), root->docWidth(), (int)ceilf(oldBottom - oldTop));
1311         root->layer()->paint(&context, dirtyRect);
1312         *newBottom = root->bestTruncatedAt();
1313         if (*newBottom == 0)
1314             *newBottom = oldBottom;
1315     } else
1316         *newBottom = oldBottom;
1317 }
1318
1319 Frame* Frame::frameForWidget(const Widget* widget)
1320 {
1321     ASSERT_ARG(widget, widget);
1322
1323     if (RenderWidget* renderer = RenderWidget::find(widget))
1324         if (Node* node = renderer->node())
1325             return node->document()->frame();
1326
1327     // Assume all widgets are either a FrameView or owned by a RenderWidget.
1328     // FIXME: That assumption is not right for scroll bars!
1329     ASSERT(widget->isFrameView());
1330     return static_cast<const FrameView*>(widget)->frame();
1331 }
1332
1333 void Frame::forceLayout(bool allowSubtree)
1334 {
1335     FrameView *v = d->m_view.get();
1336     if (v) {
1337         v->layout(allowSubtree);
1338         // We cannot unschedule a pending relayout, since the force can be called with
1339         // a tiny rectangle from a drawRect update.  By unscheduling we in effect
1340         // "validate" and stop the necessary full repaint from occurring.  Basically any basic
1341         // append/remove DHTML is broken by this call.  For now, I have removed the optimization
1342         // until we have a better invalidation stategy. -dwh
1343         //v->unscheduleRelayout();
1344     }
1345 }
1346
1347 void Frame::forceLayoutWithPageWidthRange(float minPageWidth, float maxPageWidth, bool adjustViewSize)
1348 {
1349     // Dumping externalRepresentation(m_frame->renderer()).ascii() is a good trick to see
1350     // the state of things before and after the layout
1351     RenderView *root = static_cast<RenderView*>(document()->renderer());
1352     if (root) {
1353         // This magic is basically copied from khtmlview::print
1354         int pageW = (int)ceilf(minPageWidth);
1355         root->setWidth(pageW);
1356         root->setNeedsLayoutAndPrefWidthsRecalc();
1357         forceLayout();
1358         
1359         // If we don't fit in the minimum page width, we'll lay out again. If we don't fit in the
1360         // maximum page width, we will lay out to the maximum page width and clip extra content.
1361         // FIXME: We are assuming a shrink-to-fit printing implementation.  A cropping
1362         // implementation should not do this!
1363         int rightmostPos = root->rightmostPosition();
1364         if (rightmostPos > minPageWidth) {
1365             pageW = min(rightmostPos, (int)ceilf(maxPageWidth));
1366             root->setWidth(pageW);
1367             root->setNeedsLayoutAndPrefWidthsRecalc();
1368             forceLayout();
1369         }
1370     }
1371
1372     if (adjustViewSize && view())
1373         view()->adjustViewSize();
1374 }
1375
1376 void Frame::sendResizeEvent()
1377 {
1378     if (Document* doc = document())
1379         doc->dispatchWindowEvent(EventNames::resizeEvent, false, false);
1380 }
1381
1382 void Frame::sendScrollEvent()
1383 {
1384     FrameView* v = d->m_view.get();
1385     if (!v)
1386         return;
1387     v->setWasScrolledByUser(true);
1388     Document* doc = document();
1389     if (!doc)
1390         return;
1391     doc->dispatchHTMLEvent(scrollEvent, true, false);
1392 }
1393
1394 void Frame::clearTimers(FrameView *view, Document *document)
1395 {
1396     if (view) {
1397         view->unscheduleRelayout();
1398         if (view->frame()) {
1399             if (document && document->renderer() && document->renderer()->hasLayer())
1400                 document->renderer()->layer()->suspendMarquees();
1401             view->frame()->animation()->suspendAnimations(document);
1402             view->frame()->eventHandler()->stopAutoscrollTimer();
1403         }
1404     }
1405 }
1406
1407 void Frame::clearTimers()
1408 {
1409     clearTimers(d->m_view.get(), document());
1410 }
1411
1412 RenderStyle *Frame::styleForSelectionStart(Node *&nodeToRemove) const
1413 {
1414     nodeToRemove = 0;
1415     
1416     if (!document())
1417         return 0;
1418     if (selection()->isNone())
1419         return 0;
1420     
1421     Position pos = selection()->selection().visibleStart().deepEquivalent();
1422     if (!pos.isCandidate())
1423         return 0;
1424     Node *node = pos.node();
1425     if (!node)
1426         return 0;
1427     
1428     if (!d->m_typingStyle)
1429         return node->renderer()->style();
1430     
1431     ExceptionCode ec = 0;
1432     RefPtr<Element> styleElement = document()->createElementNS(xhtmlNamespaceURI, "span", ec);
1433     ASSERT(ec == 0);
1434     
1435     String styleText = d->m_typingStyle->cssText() + " display: inline";
1436     styleElement->setAttribute(styleAttr, styleText.impl(), ec);
1437     ASSERT(ec == 0);
1438     
1439     styleElement->appendChild(document()->createEditingTextNode(""), ec);
1440     ASSERT(ec == 0);
1441     
1442     node->parentNode()->appendChild(styleElement, ec);
1443     ASSERT(ec == 0);
1444     
1445     nodeToRemove = styleElement.get();    
1446     return styleElement->renderer() ? styleElement->renderer()->style() : 0;
1447 }
1448
1449 void Frame::setSelectionFromNone()
1450 {
1451     // Put a caret inside the body if the entire frame is editable (either the 
1452     // entire WebView is editable or designMode is on for this document).
1453     Document *doc = document();
1454     if (!doc || !selection()->isNone() || !isContentEditable())
1455         return;
1456         
1457     Node* node = doc->documentElement();
1458     while (node && !node->hasTagName(bodyTag))
1459         node = node->traverseNextNode();
1460     if (node)
1461         selection()->setSelection(Selection(Position(node, 0), DOWNSTREAM));
1462 }
1463
1464 bool Frame::inViewSourceMode() const
1465 {
1466     return d->m_inViewSourceMode;
1467 }
1468
1469 void Frame::setInViewSourceMode(bool mode) const
1470 {
1471     d->m_inViewSourceMode = mode;
1472 }
1473
1474 UChar Frame::backslashAsCurrencySymbol() const
1475 {
1476     Document *doc = document();
1477     if (!doc)
1478         return '\\';
1479     TextResourceDecoder *decoder = doc->decoder();
1480     if (!decoder)
1481         return '\\';
1482
1483     return decoder->encoding().backslashAsCurrencySymbol();
1484 }
1485
1486 // Searches from the beginning of the document if nothing is selected.
1487 bool Frame::findString(const String& target, bool forward, bool caseFlag, bool wrapFlag, bool startInSelection)
1488 {
1489     if (target.isEmpty() || !document())
1490         return false;
1491     
1492     if (excludeFromTextSearch())
1493         return false;
1494     
1495     // Start from an edge of the selection, if there's a selection that's not in shadow content. Which edge
1496     // is used depends on whether we're searching forward or backward, and whether startInSelection is set.
1497     RefPtr<Range> searchRange(rangeOfContents(document()));
1498     Selection selection = this->selection()->selection();
1499
1500     if (forward)
1501         setStart(searchRange.get(), startInSelection ? selection.visibleStart() : selection.visibleEnd());
1502     else
1503         setEnd(searchRange.get(), startInSelection ? selection.visibleEnd() : selection.visibleStart());
1504
1505     Node* shadowTreeRoot = selection.shadowTreeRootNode();
1506     if (shadowTreeRoot) {
1507         ExceptionCode ec = 0;
1508         if (forward)
1509             searchRange->setEnd(shadowTreeRoot, shadowTreeRoot->childNodeCount(), ec);
1510         else
1511             searchRange->setStart(shadowTreeRoot, 0, ec);
1512     }
1513
1514     RefPtr<Range> resultRange(findPlainText(searchRange.get(), target, forward, caseFlag));
1515     // If we started in the selection and the found range exactly matches the existing selection, find again.
1516     // Build a selection with the found range to remove collapsed whitespace.
1517     // Compare ranges instead of selection objects to ignore the way that the current selection was made.
1518     if (startInSelection && *Selection(resultRange.get()).toRange() == *selection.toRange()) {
1519         searchRange = rangeOfContents(document());
1520         if (forward)
1521             setStart(searchRange.get(), selection.visibleEnd());
1522         else
1523             setEnd(searchRange.get(), selection.visibleStart());
1524
1525         if (shadowTreeRoot) {
1526             ExceptionCode ec = 0;
1527             if (forward)
1528                 searchRange->setEnd(shadowTreeRoot, shadowTreeRoot->childNodeCount(), ec);
1529             else
1530                 searchRange->setStart(shadowTreeRoot, 0, ec);
1531         }
1532
1533         resultRange = findPlainText(searchRange.get(), target, forward, caseFlag);
1534     }
1535     
1536     ExceptionCode exception = 0;
1537
1538     // If nothing was found in the shadow tree, search in main content following the shadow tree.
1539     if (resultRange->collapsed(exception) && shadowTreeRoot) {
1540         searchRange = rangeOfContents(document());
1541         if (forward)
1542             searchRange->setStartAfter(shadowTreeRoot->shadowParentNode(), exception);
1543         else
1544             searchRange->setEndBefore(shadowTreeRoot->shadowParentNode(), exception);
1545
1546         resultRange = findPlainText(searchRange.get(), target, forward, caseFlag);
1547     }
1548     
1549     if (!editor()->insideVisibleArea(resultRange.get())) {
1550         resultRange = editor()->nextVisibleRange(resultRange.get(), target, forward, caseFlag, wrapFlag);
1551         if (!resultRange)
1552             return false;
1553     }
1554
1555     // If we didn't find anything and we're wrapping, search again in the entire document (this will
1556     // redundantly re-search the area already searched in some cases).
1557     if (resultRange->collapsed(exception) && wrapFlag) {
1558         searchRange = rangeOfContents(document());
1559         resultRange = findPlainText(searchRange.get(), target, forward, caseFlag);
1560         // We used to return false here if we ended up with the same range that we started with
1561         // (e.g., the selection was already the only instance of this text). But we decided that
1562         // this should be a success case instead, so we'll just fall through in that case.
1563     }
1564
1565     if (resultRange->collapsed(exception))
1566         return false;
1567
1568     this->selection()->setSelection(Selection(resultRange.get(), DOWNSTREAM));
1569     revealSelection();
1570     return true;
1571 }
1572
1573 unsigned Frame::markAllMatchesForText(const String& target, bool caseFlag, unsigned limit)
1574 {
1575     if (target.isEmpty() || !document())
1576         return 0;
1577     
1578     RefPtr<Range> searchRange(rangeOfContents(document()));
1579     
1580     ExceptionCode exception = 0;
1581     unsigned matchCount = 0;
1582     do {
1583         RefPtr<Range> resultRange(findPlainText(searchRange.get(), target, true, caseFlag));
1584         if (resultRange->collapsed(exception)) {
1585             if (!resultRange->startContainer()->isInShadowTree())
1586                 break;
1587
1588             searchRange = rangeOfContents(document());
1589             searchRange->setStartAfter(resultRange->startContainer()->shadowAncestorNode(), exception);
1590             continue;
1591         }
1592         
1593         // A non-collapsed result range can in some funky whitespace cases still not
1594         // advance the range's start position (4509328). Break to avoid infinite loop.
1595         VisiblePosition newStart = endVisiblePosition(resultRange.get(), DOWNSTREAM);
1596         if (newStart == startVisiblePosition(searchRange.get(), DOWNSTREAM))
1597             break;
1598
1599         // Only treat the result as a match if it is visible
1600         if (editor()->insideVisibleArea(resultRange.get())) {
1601             ++matchCount;
1602             document()->addMarker(resultRange.get(), DocumentMarker::TextMatch);
1603         }
1604         
1605         // Stop looking if we hit the specified limit. A limit of 0 means no limit.
1606         if (limit > 0 && matchCount >= limit)
1607             break;
1608         
1609         setStart(searchRange.get(), newStart);
1610         Node* shadowTreeRoot = searchRange->shadowTreeRootNode();
1611         if (searchRange->collapsed(exception) && shadowTreeRoot)
1612             searchRange->setEnd(shadowTreeRoot, shadowTreeRoot->childNodeCount(), exception);
1613     } while (true);
1614     
1615     // Do a "fake" paint in order to execute the code that computes the rendered rect for 
1616     // each text match.
1617     Document* doc = document();
1618     if (doc && d->m_view && contentRenderer()) {
1619         doc->updateLayout(); // Ensure layout is up to date.
1620         IntRect visibleRect(enclosingIntRect(d->m_view->visibleContentRect()));
1621         if (!visibleRect.isEmpty()) {
1622             GraphicsContext context((PlatformGraphicsContext*)0);
1623             context.setPaintingDisabled(true);
1624             paint(&context, visibleRect);
1625         }
1626     }
1627     
1628     return matchCount;
1629 }
1630
1631 bool Frame::markedTextMatchesAreHighlighted() const
1632 {
1633     return d->m_highlightTextMatches;
1634 }
1635
1636 void Frame::setMarkedTextMatchesAreHighlighted(bool flag)
1637 {
1638     if (flag == d->m_highlightTextMatches || !document())
1639         return;
1640     
1641     d->m_highlightTextMatches = flag;
1642     document()->repaintMarkers(DocumentMarker::TextMatch);
1643 }
1644
1645 FrameTree* Frame::tree() const
1646 {
1647     return &d->m_treeNode;
1648 }
1649
1650 DOMWindow* Frame::domWindow() const
1651 {
1652     if (!d->m_domWindow)
1653         d->m_domWindow = DOMWindow::create(const_cast<Frame*>(this));
1654
1655     return d->m_domWindow.get();
1656 }
1657
1658 void Frame::clearFormerDOMWindow(DOMWindow* window)
1659 {
1660     d->m_liveFormerWindows.remove(window);    
1661 }
1662
1663 Page* Frame::page() const
1664 {
1665     return d->m_page;
1666 }
1667
1668 EventHandler* Frame::eventHandler() const
1669 {
1670     return &d->m_eventHandler;
1671 }
1672
1673 void Frame::pageDestroyed()
1674 {
1675     if (Frame* parent = tree()->parent())
1676         parent->loader()->checkLoadComplete();
1677
1678     // FIXME: It's unclear as to why this is called more than once, but it is,
1679     // so page() could be NULL.
1680     if (page() && page()->focusController()->focusedFrame() == this)
1681         page()->focusController()->setFocusedFrame(0);
1682
1683     // This will stop any JS timers
1684     if (script()->haveWindowShell())
1685         script()->windowShell()->disconnectFrame();
1686
1687     script()->clearScriptObjects();
1688
1689     d->m_page = 0;
1690 }
1691
1692 void Frame::disconnectOwnerElement()
1693 {
1694     if (d->m_ownerElement) {
1695         if (Document* doc = document())
1696             doc->clearAXObjectCache();
1697         d->m_ownerElement->m_contentFrame = 0;
1698         if (d->m_page)
1699             d->m_page->decrementFrameCount();
1700     }
1701     d->m_ownerElement = 0;
1702 }
1703
1704 String Frame::documentTypeString() const
1705 {
1706     if (Document* doc = document()) {
1707         if (DocumentType* doctype = doc->doctype())
1708             return createMarkup(doctype);
1709     }
1710
1711     return String();
1712 }
1713
1714 bool Frame::prohibitsScrolling() const
1715 {
1716     return d->m_prohibitsScrolling;
1717 }
1718
1719 void Frame::setProhibitsScrolling(bool prohibit)
1720 {
1721     d->m_prohibitsScrolling = prohibit;
1722 }
1723
1724 void Frame::focusWindow()
1725 {
1726     if (!page())
1727         return;
1728
1729     // If we're a top level window, bring the window to the front.
1730     if (!tree()->parent())
1731         page()->chrome()->focus();
1732
1733     eventHandler()->focusDocumentView();
1734 }
1735
1736 void Frame::unfocusWindow()
1737 {
1738     if (!page())
1739         return;
1740     
1741     // If we're a top level window, deactivate the window.
1742     if (!tree()->parent())
1743         page()->chrome()->unfocus();
1744 }
1745
1746 bool Frame::shouldClose()
1747 {
1748     Chrome* chrome = page() ? page()->chrome() : 0;
1749     if (!chrome || !chrome->canRunBeforeUnloadConfirmPanel())
1750         return true;
1751
1752     RefPtr<Document> doc = document();
1753     if (!doc)
1754         return true;
1755     HTMLElement* body = doc->body();
1756     if (!body)
1757         return true;
1758
1759     RefPtr<BeforeUnloadEvent> beforeUnloadEvent = BeforeUnloadEvent::create();
1760     beforeUnloadEvent->setTarget(doc);
1761     doc->handleWindowEvent(beforeUnloadEvent.get(), false);
1762
1763     if (!beforeUnloadEvent->defaultPrevented() && doc)
1764         doc->defaultEventHandler(beforeUnloadEvent.get());
1765     if (beforeUnloadEvent->result().isNull())
1766         return true;
1767
1768     String text = beforeUnloadEvent->result();
1769     text.replace('\\', backslashAsCurrencySymbol());
1770
1771     return chrome->runBeforeUnloadConfirmPanel(text, this);
1772 }
1773
1774 void Frame::scheduleClose()
1775 {
1776     if (!shouldClose())
1777         return;
1778
1779     Chrome* chrome = page() ? page()->chrome() : 0;
1780     if (chrome)
1781         chrome->closeWindowSoon();
1782 }
1783
1784 void Frame::respondToChangedSelection(const Selection& oldSelection, bool closeTyping)
1785 {
1786     if (document()) {
1787         bool isContinuousSpellCheckingEnabled = editor()->isContinuousSpellCheckingEnabled();
1788         bool isContinuousGrammarCheckingEnabled = isContinuousSpellCheckingEnabled && editor()->isGrammarCheckingEnabled();
1789         if (isContinuousSpellCheckingEnabled) {
1790             Selection newAdjacentWords;
1791             Selection newSelectedSentence;
1792             if (selection()->selection().isContentEditable()) {
1793                 VisiblePosition newStart(selection()->selection().visibleStart());
1794                 newAdjacentWords = Selection(startOfWord(newStart, LeftWordIfOnBoundary), endOfWord(newStart, RightWordIfOnBoundary));
1795                 if (isContinuousGrammarCheckingEnabled)
1796                     newSelectedSentence = Selection(startOfSentence(newStart), endOfSentence(newStart));
1797             }
1798
1799             // When typing we check spelling elsewhere, so don't redo it here.
1800             // If this is a change in selection resulting from a delete operation,
1801             // oldSelection may no longer be in the document.
1802             if (closeTyping && oldSelection.isContentEditable() && oldSelection.start().node() && oldSelection.start().node()->inDocument()) {
1803                 VisiblePosition oldStart(oldSelection.visibleStart());
1804                 Selection oldAdjacentWords = Selection(startOfWord(oldStart, LeftWordIfOnBoundary), endOfWord(oldStart, RightWordIfOnBoundary));   
1805                 if (oldAdjacentWords != newAdjacentWords) {
1806                     editor()->markMisspellings(oldAdjacentWords);
1807                     if (isContinuousGrammarCheckingEnabled) {
1808                         Selection oldSelectedSentence = Selection(startOfSentence(oldStart), endOfSentence(oldStart));   
1809                         if (oldSelectedSentence != newSelectedSentence)
1810                             editor()->markBadGrammar(oldSelectedSentence);
1811                     }
1812                 }
1813             }
1814
1815             // This only erases markers that are in the first unit (word or sentence) of the selection.
1816             // Perhaps peculiar, but it matches AppKit.
1817             if (RefPtr<Range> wordRange = newAdjacentWords.toRange())
1818                 document()->removeMarkers(wordRange.get(), DocumentMarker::Spelling);
1819             if (RefPtr<Range> sentenceRange = newSelectedSentence.toRange())
1820                 document()->removeMarkers(sentenceRange.get(), DocumentMarker::Grammar);
1821         }
1822
1823         // When continuous spell checking is off, existing markers disappear after the selection changes.
1824         if (!isContinuousSpellCheckingEnabled)
1825             document()->removeMarkers(DocumentMarker::Spelling);
1826         if (!isContinuousGrammarCheckingEnabled)
1827             document()->removeMarkers(DocumentMarker::Grammar);
1828     }
1829
1830     editor()->respondToChangedSelection(oldSelection);
1831 }
1832
1833 VisiblePosition Frame::visiblePositionForPoint(const IntPoint& framePoint)
1834 {
1835     HitTestResult result = eventHandler()->hitTestResultAtPoint(framePoint, true);
1836     Node* node = result.innerNode();
1837     if (!node)
1838         return VisiblePosition();
1839     RenderObject* renderer = node->renderer();
1840     if (!renderer)
1841         return VisiblePosition();
1842     VisiblePosition visiblePos = renderer->positionForCoordinates(result.localPoint().x(), result.localPoint().y());
1843     if (visiblePos.isNull())
1844         visiblePos = VisiblePosition(Position(node, 0));
1845     return visiblePos;
1846 }
1847     
1848 Document* Frame::documentAtPoint(const IntPoint& point)
1849 {  
1850     if (!view()) 
1851         return 0;
1852     
1853     IntPoint pt = view()->windowToContents(point);
1854     HitTestResult result = HitTestResult(pt);
1855     
1856     if (contentRenderer())
1857         result = eventHandler()->hitTestResultAtPoint(pt, false);
1858     return result.innerNode() ? result.innerNode()->document() : 0;
1859 }
1860     
1861 FramePrivate::FramePrivate(Page* page, Frame* parent, Frame* thisFrame, HTMLFrameOwnerElement* ownerElement,
1862                            FrameLoaderClient* frameLoaderClient)
1863     : m_page(page)
1864     , m_treeNode(thisFrame, parent)
1865     , m_loader(thisFrame, frameLoaderClient)
1866     , m_ownerElement(ownerElement)
1867     , m_script(thisFrame)
1868     , m_zoomFactor(parent ? parent->d->m_zoomFactor : 1.0f)
1869     , m_selectionGranularity(CharacterGranularity)
1870     , m_selectionController(thisFrame)
1871     , m_caretBlinkTimer(thisFrame, &Frame::caretBlinkTimerFired)
1872     , m_editor(thisFrame)
1873     , m_eventHandler(thisFrame)
1874     , m_animationController(thisFrame)
1875     , m_lifeSupportTimer(thisFrame, &Frame::lifeSupportTimerFired)
1876     , m_paintRestriction(PaintRestrictionNone)
1877     , m_caretVisible(false)
1878     , m_caretPaint(true)
1879     , m_isPainting(false)
1880     , m_highlightTextMatches(false)
1881     , m_inViewSourceMode(false)
1882     , m_prohibitsScrolling(false)
1883     , m_needsReapplyStyles(false)
1884     , m_isDisconnected(false)
1885     , m_excludeFromTextSearch(false)
1886 #if FRAME_LOADS_USER_STYLESHEET
1887     , m_userStyleSheetLoader(0)
1888 #endif
1889 {
1890 }
1891
1892 FramePrivate::~FramePrivate()
1893 {
1894 }
1895
1896 } // namespace WebCore