1312f0b0460aa90bfa4d843d9e668e43781da6ec
[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 // returns FloatRect because going through IntRect would truncate any floats
1107 FloatRect Frame::selectionRect(bool clipToVisibleContent) const
1108 {
1109     RenderView* root = contentRenderer();
1110     if (!root)
1111         return IntRect();
1112     
1113     IntRect selectionRect = root->selectionRect(clipToVisibleContent);
1114     return clipToVisibleContent ? intersection(selectionRect, d->m_view->visibleContentRect()) : selectionRect;
1115 }
1116
1117 void Frame::selectionTextRects(Vector<FloatRect>& rects, bool clipToVisibleContent) const
1118 {
1119     RenderView* root = contentRenderer();
1120     if (!root)
1121         return;
1122
1123     RefPtr<Range> selectedRange = selection()->toRange();
1124
1125     Vector<IntRect> intRects;
1126     selectedRange->addLineBoxRects(intRects, true);
1127
1128     unsigned size = intRects.size();
1129     FloatRect visibleContentRect = d->m_view->visibleContentRect();
1130     for (unsigned i = 0; i < size; ++i)
1131         if (clipToVisibleContent)
1132             rects.append(intersection(intRects[i], visibleContentRect));
1133         else
1134             rects.append(intRects[i]);
1135 }
1136
1137
1138 bool Frame::isFrameSet() const
1139 {
1140     Document* document = d->m_doc.get();
1141     if (!document || !document->isHTMLDocument())
1142         return false;
1143     Node *body = static_cast<HTMLDocument*>(document)->body();
1144     return body && body->renderer() && body->hasTagName(framesetTag);
1145 }
1146
1147 // Scans logically forward from "start", including any child frames
1148 static HTMLFormElement *scanForForm(Node *start)
1149 {
1150     Node *n;
1151     for (n = start; n; n = n->traverseNextNode()) {
1152         if (n->hasTagName(formTag))
1153             return static_cast<HTMLFormElement*>(n);
1154         else if (n->isHTMLElement() && static_cast<HTMLElement*>(n)->isGenericFormElement())
1155             return static_cast<HTMLFormControlElement*>(n)->form();
1156         else if (n->hasTagName(frameTag) || n->hasTagName(iframeTag)) {
1157             Node *childDoc = static_cast<HTMLFrameElementBase*>(n)->contentDocument();
1158             if (HTMLFormElement *frameResult = scanForForm(childDoc))
1159                 return frameResult;
1160         }
1161     }
1162     return 0;
1163 }
1164
1165 // We look for either the form containing the current focus, or for one immediately after it
1166 HTMLFormElement *Frame::currentForm() const
1167 {
1168     // start looking either at the active (first responder) node, or where the selection is
1169     Node *start = d->m_doc ? d->m_doc->focusedNode() : 0;
1170     if (!start)
1171         start = selection()->start().node();
1172     
1173     // try walking up the node tree to find a form element
1174     Node *n;
1175     for (n = start; n; n = n->parentNode()) {
1176         if (n->hasTagName(formTag))
1177             return static_cast<HTMLFormElement*>(n);
1178         else if (n->isHTMLElement()
1179                    && static_cast<HTMLElement*>(n)->isGenericFormElement())
1180             return static_cast<HTMLFormControlElement*>(n)->form();
1181     }
1182     
1183     // try walking forward in the node tree to find a form element
1184     return start ? scanForForm(start) : 0;
1185 }
1186
1187 // FIXME: should this go in SelectionController?
1188 void Frame::revealSelection(const RenderLayer::ScrollAlignment& alignment) const
1189 {
1190     IntRect rect;
1191     
1192     switch (selection()->state()) {
1193         case Selection::NONE:
1194             return;
1195             
1196         case Selection::CARET:
1197             rect = selection()->caretRect();
1198             break;
1199             
1200         case Selection::RANGE:
1201             rect = enclosingIntRect(selectionRect(false));
1202             break;
1203     }
1204
1205     Position start = selection()->start();
1206
1207     ASSERT(start.node());
1208     if (start.node() && start.node()->renderer()) {
1209         // FIXME: This code only handles scrolling the startContainer's layer, but
1210         // the selection rect could intersect more than just that. 
1211         // See <rdar://problem/4799899>.
1212         if (RenderLayer *layer = start.node()->renderer()->enclosingLayer())
1213             layer->scrollRectToVisible(rect, false, alignment, alignment);
1214     }
1215 }
1216
1217 void Frame::revealCaret(const RenderLayer::ScrollAlignment& alignment) const
1218 {
1219     if (selection()->isNone())
1220         return;
1221
1222     Position extent = selection()->extent();
1223     if (extent.node() && extent.node()->renderer()) {
1224         IntRect extentRect = VisiblePosition(extent).caretRect();
1225         RenderLayer* layer = extent.node()->renderer()->enclosingLayer();
1226         if (layer)
1227             layer->scrollRectToVisible(extentRect, false, alignment, alignment);
1228     }
1229 }
1230
1231 // FIXME: why is this here instead of on the FrameView?
1232 void Frame::paint(GraphicsContext* p, const IntRect& rect)
1233 {
1234 #ifndef NDEBUG
1235     bool fillWithRed;
1236     if (!document() || document()->printing())
1237         fillWithRed = false; // Printing, don't fill with red (can't remember why).
1238     else if (document()->ownerElement())
1239         fillWithRed = false; // Subframe, don't fill with red.
1240     else if (view() && view()->isTransparent())
1241         fillWithRed = false; // Transparent, don't fill with red.
1242     else if (d->m_paintRestriction == PaintRestrictionSelectionOnly || d->m_paintRestriction == PaintRestrictionSelectionOnlyBlackText)
1243         fillWithRed = false; // Selections are transparent, don't fill with red.
1244     else if (d->m_elementToDraw)
1245         fillWithRed = false; // Element images are transparent, don't fill with red.
1246     else
1247         fillWithRed = true;
1248     
1249     if (fillWithRed)
1250         p->fillRect(rect, Color(0xFF, 0, 0));
1251 #endif
1252
1253     bool isTopLevelPainter = !s_currentPaintTimeStamp;
1254     if (isTopLevelPainter)
1255         s_currentPaintTimeStamp = currentTime();
1256     
1257     if (contentRenderer()) {
1258         ASSERT(d->m_view && !d->m_view->needsLayout());
1259         ASSERT(!d->m_isPainting);
1260         
1261         d->m_isPainting = true;
1262         
1263         // d->m_elementToDraw is used to draw only one element
1264         RenderObject* eltRenderer = d->m_elementToDraw ? d->m_elementToDraw->renderer() : 0;
1265         if (d->m_paintRestriction == PaintRestrictionNone)
1266             document()->invalidateRenderedRectsForMarkersInRect(rect);
1267         contentRenderer()->layer()->paint(p, rect, d->m_paintRestriction, eltRenderer);
1268         
1269         d->m_isPainting = false;
1270
1271 #if ENABLE(DASHBOARD_SUPPORT)
1272         // Regions may have changed as a result of the visibility/z-index of element changing.
1273         if (document()->dashboardRegionsDirty())
1274             view()->updateDashboardRegions();
1275 #endif
1276     } else
1277         LOG_ERROR("called Frame::paint with nil renderer");
1278         
1279     if (isTopLevelPainter)
1280         s_currentPaintTimeStamp = 0;
1281 }
1282
1283 void Frame::setPaintRestriction(PaintRestriction pr)
1284 {
1285     d->m_paintRestriction = pr;
1286 }
1287     
1288 bool Frame::isPainting() const
1289 {
1290     return d->m_isPainting;
1291 }
1292
1293 void Frame::adjustPageHeight(float *newBottom, float oldTop, float oldBottom, float bottomLimit)
1294 {
1295     RenderView* root = contentRenderer();
1296     if (root) {
1297         // Use a context with painting disabled.
1298         GraphicsContext context((PlatformGraphicsContext*)0);
1299         root->setTruncatedAt((int)floorf(oldBottom));
1300         IntRect dirtyRect(0, (int)floorf(oldTop), root->docWidth(), (int)ceilf(oldBottom - oldTop));
1301         root->layer()->paint(&context, dirtyRect);
1302         *newBottom = root->bestTruncatedAt();
1303         if (*newBottom == 0)
1304             *newBottom = oldBottom;
1305     } else
1306         *newBottom = oldBottom;
1307 }
1308
1309 Frame* Frame::frameForWidget(const Widget* widget)
1310 {
1311     ASSERT_ARG(widget, widget);
1312
1313     if (RenderWidget* renderer = RenderWidget::find(widget))
1314         if (Node* node = renderer->node())
1315             return node->document()->frame();
1316
1317     // Assume all widgets are either a FrameView or owned by a RenderWidget.
1318     // FIXME: That assumption is not right for scroll bars!
1319     ASSERT(widget->isFrameView());
1320     return static_cast<const FrameView*>(widget)->frame();
1321 }
1322
1323 void Frame::forceLayout(bool allowSubtree)
1324 {
1325     FrameView *v = d->m_view.get();
1326     if (v) {
1327         v->layout(allowSubtree);
1328         // We cannot unschedule a pending relayout, since the force can be called with
1329         // a tiny rectangle from a drawRect update.  By unscheduling we in effect
1330         // "validate" and stop the necessary full repaint from occurring.  Basically any basic
1331         // append/remove DHTML is broken by this call.  For now, I have removed the optimization
1332         // until we have a better invalidation stategy. -dwh
1333         //v->unscheduleRelayout();
1334     }
1335 }
1336
1337 void Frame::forceLayoutWithPageWidthRange(float minPageWidth, float maxPageWidth, bool adjustViewSize)
1338 {
1339     // Dumping externalRepresentation(m_frame->renderer()).ascii() is a good trick to see
1340     // the state of things before and after the layout
1341     RenderView *root = static_cast<RenderView*>(document()->renderer());
1342     if (root) {
1343         // This magic is basically copied from khtmlview::print
1344         int pageW = (int)ceilf(minPageWidth);
1345         root->setWidth(pageW);
1346         root->setNeedsLayoutAndPrefWidthsRecalc();
1347         forceLayout();
1348         
1349         // If we don't fit in the minimum page width, we'll lay out again. If we don't fit in the
1350         // maximum page width, we will lay out to the maximum page width and clip extra content.
1351         // FIXME: We are assuming a shrink-to-fit printing implementation.  A cropping
1352         // implementation should not do this!
1353         int rightmostPos = root->rightmostPosition();
1354         if (rightmostPos > minPageWidth) {
1355             pageW = min(rightmostPos, (int)ceilf(maxPageWidth));
1356             root->setWidth(pageW);
1357             root->setNeedsLayoutAndPrefWidthsRecalc();
1358             forceLayout();
1359         }
1360     }
1361
1362     if (adjustViewSize && view())
1363         view()->adjustViewSize();
1364 }
1365
1366 void Frame::sendResizeEvent()
1367 {
1368     if (Document* doc = document())
1369         doc->dispatchWindowEvent(EventNames::resizeEvent, false, false);
1370 }
1371
1372 void Frame::sendScrollEvent()
1373 {
1374     FrameView* v = d->m_view.get();
1375     if (!v)
1376         return;
1377     v->setWasScrolledByUser(true);
1378     Document* doc = document();
1379     if (!doc)
1380         return;
1381     doc->dispatchHTMLEvent(scrollEvent, true, false);
1382 }
1383
1384 void Frame::clearTimers(FrameView *view, Document *document)
1385 {
1386     if (view) {
1387         view->unscheduleRelayout();
1388         if (view->frame()) {
1389             if (document && document->renderer() && document->renderer()->hasLayer())
1390                 document->renderer()->layer()->suspendMarquees();
1391             view->frame()->animation()->suspendAnimations(document);
1392             view->frame()->eventHandler()->stopAutoscrollTimer();
1393         }
1394     }
1395 }
1396
1397 void Frame::clearTimers()
1398 {
1399     clearTimers(d->m_view.get(), document());
1400 }
1401
1402 RenderStyle *Frame::styleForSelectionStart(Node *&nodeToRemove) const
1403 {
1404     nodeToRemove = 0;
1405     
1406     if (!document())
1407         return 0;
1408     if (selection()->isNone())
1409         return 0;
1410     
1411     Position pos = selection()->selection().visibleStart().deepEquivalent();
1412     if (!pos.isCandidate())
1413         return 0;
1414     Node *node = pos.node();
1415     if (!node)
1416         return 0;
1417     
1418     if (!d->m_typingStyle)
1419         return node->renderer()->style();
1420     
1421     ExceptionCode ec = 0;
1422     RefPtr<Element> styleElement = document()->createElementNS(xhtmlNamespaceURI, "span", ec);
1423     ASSERT(ec == 0);
1424     
1425     String styleText = d->m_typingStyle->cssText() + " display: inline";
1426     styleElement->setAttribute(styleAttr, styleText.impl(), ec);
1427     ASSERT(ec == 0);
1428     
1429     styleElement->appendChild(document()->createEditingTextNode(""), ec);
1430     ASSERT(ec == 0);
1431     
1432     node->parentNode()->appendChild(styleElement, ec);
1433     ASSERT(ec == 0);
1434     
1435     nodeToRemove = styleElement.get();    
1436     return styleElement->renderer() ? styleElement->renderer()->style() : 0;
1437 }
1438
1439 void Frame::setSelectionFromNone()
1440 {
1441     // Put a caret inside the body if the entire frame is editable (either the 
1442     // entire WebView is editable or designMode is on for this document).
1443     Document *doc = document();
1444     if (!doc || !selection()->isNone() || !isContentEditable())
1445         return;
1446         
1447     Node* node = doc->documentElement();
1448     while (node && !node->hasTagName(bodyTag))
1449         node = node->traverseNextNode();
1450     if (node)
1451         selection()->setSelection(Selection(Position(node, 0), DOWNSTREAM));
1452 }
1453
1454 bool Frame::inViewSourceMode() const
1455 {
1456     return d->m_inViewSourceMode;
1457 }
1458
1459 void Frame::setInViewSourceMode(bool mode) const
1460 {
1461     d->m_inViewSourceMode = mode;
1462 }
1463
1464 UChar Frame::backslashAsCurrencySymbol() const
1465 {
1466     Document *doc = document();
1467     if (!doc)
1468         return '\\';
1469     TextResourceDecoder *decoder = doc->decoder();
1470     if (!decoder)
1471         return '\\';
1472
1473     return decoder->encoding().backslashAsCurrencySymbol();
1474 }
1475
1476 static bool isInShadowTree(Node* node)
1477 {
1478     for (Node* n = node; n; n = n->parentNode())
1479         if (n->isShadowNode())
1480             return true;
1481     return false;
1482 }
1483
1484 // Searches from the beginning of the document if nothing is selected.
1485 bool Frame::findString(const String& target, bool forward, bool caseFlag, bool wrapFlag, bool startInSelection)
1486 {
1487     if (target.isEmpty() || !document())
1488         return false;
1489     
1490     // Start from an edge of the selection, if there's a selection that's not in shadow content. Which edge
1491     // is used depends on whether we're searching forward or backward, and whether startInSelection is set.
1492     RefPtr<Range> searchRange(rangeOfContents(document()));
1493     Selection selection = this->selection()->selection();
1494
1495     if (forward)
1496         setStart(searchRange.get(), startInSelection ? selection.visibleStart() : selection.visibleEnd());
1497     else
1498         setEnd(searchRange.get(), startInSelection ? selection.visibleEnd() : selection.visibleStart());
1499
1500     Node* shadowTreeRoot = selection.shadowTreeRootNode();
1501     if (shadowTreeRoot) {
1502         ExceptionCode ec = 0;
1503         if (forward)
1504             searchRange->setEnd(shadowTreeRoot, shadowTreeRoot->childNodeCount(), ec);
1505         else
1506             searchRange->setStart(shadowTreeRoot, 0, ec);
1507     }
1508
1509     RefPtr<Range> resultRange(findPlainText(searchRange.get(), target, forward, caseFlag));
1510     // If we started in the selection and the found range exactly matches the existing selection, find again.
1511     // Build a selection with the found range to remove collapsed whitespace.
1512     // Compare ranges instead of selection objects to ignore the way that the current selection was made.
1513     if (startInSelection && *Selection(resultRange.get()).toRange() == *selection.toRange()) {
1514         searchRange = rangeOfContents(document());
1515         if (forward)
1516             setStart(searchRange.get(), selection.visibleEnd());
1517         else
1518             setEnd(searchRange.get(), selection.visibleStart());
1519
1520         if (shadowTreeRoot) {
1521             ExceptionCode ec = 0;
1522             if (forward)
1523                 searchRange->setEnd(shadowTreeRoot, shadowTreeRoot->childNodeCount(), ec);
1524             else
1525                 searchRange->setStart(shadowTreeRoot, 0, ec);
1526         }
1527
1528         resultRange = findPlainText(searchRange.get(), target, forward, caseFlag);
1529     }
1530     
1531     ExceptionCode exception = 0;
1532
1533     // If nothing was found in the shadow tree, search in main content following the shadow tree.
1534     if (resultRange->collapsed(exception) && shadowTreeRoot) {
1535         searchRange = rangeOfContents(document());
1536         if (forward)
1537             searchRange->setStartAfter(shadowTreeRoot->shadowParentNode(), exception);
1538         else
1539             searchRange->setEndBefore(shadowTreeRoot->shadowParentNode(), exception);
1540
1541         resultRange = findPlainText(searchRange.get(), target, forward, caseFlag);
1542     }
1543     
1544     if (!editor()->insideVisibleArea(resultRange.get())) {
1545         resultRange = editor()->nextVisibleRange(resultRange.get(), target, forward, caseFlag);
1546         if (!resultRange)
1547             return false;
1548     }
1549
1550     // If we didn't find anything and we're wrapping, search again in the entire document (this will
1551     // redundantly re-search the area already searched in some cases).
1552     if (resultRange->collapsed(exception) && wrapFlag) {
1553         searchRange = rangeOfContents(document());
1554         resultRange = findPlainText(searchRange.get(), target, forward, caseFlag);
1555         // We used to return false here if we ended up with the same range that we started with
1556         // (e.g., the selection was already the only instance of this text). But we decided that
1557         // this should be a success case instead, so we'll just fall through in that case.
1558     }
1559
1560     if (resultRange->collapsed(exception))
1561         return false;
1562
1563     this->selection()->setSelection(Selection(resultRange.get(), DOWNSTREAM));
1564     revealSelection();
1565     return true;
1566 }
1567
1568 unsigned Frame::markAllMatchesForText(const String& target, bool caseFlag, unsigned limit)
1569 {
1570     if (target.isEmpty() || !document())
1571         return 0;
1572     
1573     RefPtr<Range> searchRange(rangeOfContents(document()));
1574     
1575     ExceptionCode exception = 0;
1576     unsigned matchCount = 0;
1577     do {
1578         RefPtr<Range> resultRange(findPlainText(searchRange.get(), target, true, caseFlag));
1579         if (resultRange->collapsed(exception)) {
1580             if (!isInShadowTree(resultRange->startContainer()))
1581                 break;
1582
1583             searchRange = rangeOfContents(document());
1584             searchRange->setStartAfter(resultRange->startContainer()->shadowAncestorNode(), exception);
1585             continue;
1586         }
1587         
1588         // A non-collapsed result range can in some funky whitespace cases still not
1589         // advance the range's start position (4509328). Break to avoid infinite loop.
1590         VisiblePosition newStart = endVisiblePosition(resultRange.get(), DOWNSTREAM);
1591         if (newStart == startVisiblePosition(searchRange.get(), DOWNSTREAM))
1592             break;
1593
1594         // Only treat the result as a match if it is visible
1595         if (editor()->insideVisibleArea(resultRange.get())) {
1596             ++matchCount;
1597             document()->addMarker(resultRange.get(), DocumentMarker::TextMatch);
1598         }
1599         
1600         // Stop looking if we hit the specified limit. A limit of 0 means no limit.
1601         if (limit > 0 && matchCount >= limit)
1602             break;
1603         
1604         setStart(searchRange.get(), newStart);
1605         Node* shadowTreeRoot = searchRange->shadowTreeRootNode();
1606         if (searchRange->collapsed(exception) && shadowTreeRoot)
1607             searchRange->setEnd(shadowTreeRoot, shadowTreeRoot->childNodeCount(), exception);
1608     } while (true);
1609     
1610     // Do a "fake" paint in order to execute the code that computes the rendered rect for 
1611     // each text match.
1612     Document* doc = document();
1613     if (doc && d->m_view && contentRenderer()) {
1614         doc->updateLayout(); // Ensure layout is up to date.
1615         IntRect visibleRect(enclosingIntRect(d->m_view->visibleContentRect()));
1616         GraphicsContext context((PlatformGraphicsContext*)0);
1617         context.setPaintingDisabled(true);
1618         paint(&context, visibleRect);
1619     }
1620     
1621     return matchCount;
1622 }
1623
1624 bool Frame::markedTextMatchesAreHighlighted() const
1625 {
1626     return d->m_highlightTextMatches;
1627 }
1628
1629 void Frame::setMarkedTextMatchesAreHighlighted(bool flag)
1630 {
1631     if (flag == d->m_highlightTextMatches || !document())
1632         return;
1633     
1634     d->m_highlightTextMatches = flag;
1635     document()->repaintMarkers(DocumentMarker::TextMatch);
1636 }
1637
1638 FrameTree* Frame::tree() const
1639 {
1640     return &d->m_treeNode;
1641 }
1642
1643 DOMWindow* Frame::domWindow() const
1644 {
1645     if (!d->m_domWindow)
1646         d->m_domWindow = DOMWindow::create(const_cast<Frame*>(this));
1647
1648     return d->m_domWindow.get();
1649 }
1650
1651 void Frame::clearFormerDOMWindow(DOMWindow* window)
1652 {
1653     d->m_liveFormerWindows.remove(window);    
1654 }
1655
1656 Page* Frame::page() const
1657 {
1658     return d->m_page;
1659 }
1660
1661 EventHandler* Frame::eventHandler() const
1662 {
1663     return &d->m_eventHandler;
1664 }
1665
1666 void Frame::pageDestroyed()
1667 {
1668     if (Frame* parent = tree()->parent())
1669         parent->loader()->checkLoadComplete();
1670
1671     // FIXME: It's unclear as to why this is called more than once, but it is,
1672     // so page() could be NULL.
1673     if (page() && page()->focusController()->focusedFrame() == this)
1674         page()->focusController()->setFocusedFrame(0);
1675
1676     // This will stop any JS timers
1677     if (script()->haveWindowShell())
1678         script()->windowShell()->disconnectFrame();
1679
1680     script()->clearScriptObjects();
1681
1682     d->m_page = 0;
1683 }
1684
1685 void Frame::disconnectOwnerElement()
1686 {
1687     if (d->m_ownerElement) {
1688         if (Document* doc = document())
1689             doc->clearAXObjectCache();
1690         d->m_ownerElement->m_contentFrame = 0;
1691         if (d->m_page)
1692             d->m_page->decrementFrameCount();
1693     }
1694     d->m_ownerElement = 0;
1695 }
1696
1697 String Frame::documentTypeString() const
1698 {
1699     if (Document* doc = document()) {
1700         if (DocumentType* doctype = doc->doctype())
1701             return createMarkup(doctype);
1702     }
1703
1704     return String();
1705 }
1706
1707 bool Frame::prohibitsScrolling() const
1708 {
1709     return d->m_prohibitsScrolling;
1710 }
1711
1712 void Frame::setProhibitsScrolling(bool prohibit)
1713 {
1714     d->m_prohibitsScrolling = prohibit;
1715 }
1716
1717 void Frame::focusWindow()
1718 {
1719     if (!page())
1720         return;
1721
1722     // If we're a top level window, bring the window to the front.
1723     if (!tree()->parent())
1724         page()->chrome()->focus();
1725
1726     eventHandler()->focusDocumentView();
1727 }
1728
1729 void Frame::unfocusWindow()
1730 {
1731     if (!page())
1732         return;
1733     
1734     // If we're a top level window, deactivate the window.
1735     if (!tree()->parent())
1736         page()->chrome()->unfocus();
1737 }
1738
1739 bool Frame::shouldClose()
1740 {
1741     Chrome* chrome = page() ? page()->chrome() : 0;
1742     if (!chrome || !chrome->canRunBeforeUnloadConfirmPanel())
1743         return true;
1744
1745     RefPtr<Document> doc = document();
1746     if (!doc)
1747         return true;
1748     HTMLElement* body = doc->body();
1749     if (!body)
1750         return true;
1751
1752     RefPtr<BeforeUnloadEvent> beforeUnloadEvent = BeforeUnloadEvent::create();
1753     beforeUnloadEvent->setTarget(doc);
1754     doc->handleWindowEvent(beforeUnloadEvent.get(), false);
1755
1756     if (!beforeUnloadEvent->defaultPrevented() && doc)
1757         doc->defaultEventHandler(beforeUnloadEvent.get());
1758     if (beforeUnloadEvent->result().isNull())
1759         return true;
1760
1761     String text = beforeUnloadEvent->result();
1762     text.replace('\\', backslashAsCurrencySymbol());
1763
1764     return chrome->runBeforeUnloadConfirmPanel(text, this);
1765 }
1766
1767 void Frame::scheduleClose()
1768 {
1769     if (!shouldClose())
1770         return;
1771
1772     Chrome* chrome = page() ? page()->chrome() : 0;
1773     if (chrome)
1774         chrome->closeWindowSoon();
1775 }
1776
1777 void Frame::respondToChangedSelection(const Selection& oldSelection, bool closeTyping)
1778 {
1779     if (document()) {
1780         bool isContinuousSpellCheckingEnabled = editor()->isContinuousSpellCheckingEnabled();
1781         bool isContinuousGrammarCheckingEnabled = isContinuousSpellCheckingEnabled && editor()->isGrammarCheckingEnabled();
1782         if (isContinuousSpellCheckingEnabled) {
1783             Selection newAdjacentWords;
1784             Selection newSelectedSentence;
1785             if (selection()->selection().isContentEditable()) {
1786                 VisiblePosition newStart(selection()->selection().visibleStart());
1787                 newAdjacentWords = Selection(startOfWord(newStart, LeftWordIfOnBoundary), endOfWord(newStart, RightWordIfOnBoundary));
1788                 if (isContinuousGrammarCheckingEnabled)
1789                     newSelectedSentence = Selection(startOfSentence(newStart), endOfSentence(newStart));
1790             }
1791
1792             // When typing we check spelling elsewhere, so don't redo it here.
1793             // If this is a change in selection resulting from a delete operation,
1794             // oldSelection may no longer be in the document.
1795             if (closeTyping && oldSelection.isContentEditable() && oldSelection.start().node() && oldSelection.start().node()->inDocument()) {
1796                 VisiblePosition oldStart(oldSelection.visibleStart());
1797                 Selection oldAdjacentWords = Selection(startOfWord(oldStart, LeftWordIfOnBoundary), endOfWord(oldStart, RightWordIfOnBoundary));   
1798                 if (oldAdjacentWords != newAdjacentWords) {
1799                     editor()->markMisspellings(oldAdjacentWords);
1800                     if (isContinuousGrammarCheckingEnabled) {
1801                         Selection oldSelectedSentence = Selection(startOfSentence(oldStart), endOfSentence(oldStart));   
1802                         if (oldSelectedSentence != newSelectedSentence)
1803                             editor()->markBadGrammar(oldSelectedSentence);
1804                     }
1805                 }
1806             }
1807
1808             // This only erases markers that are in the first unit (word or sentence) of the selection.
1809             // Perhaps peculiar, but it matches AppKit.
1810             if (RefPtr<Range> wordRange = newAdjacentWords.toRange())
1811                 document()->removeMarkers(wordRange.get(), DocumentMarker::Spelling);
1812             if (RefPtr<Range> sentenceRange = newSelectedSentence.toRange())
1813                 document()->removeMarkers(sentenceRange.get(), DocumentMarker::Grammar);
1814         }
1815
1816         // When continuous spell checking is off, existing markers disappear after the selection changes.
1817         if (!isContinuousSpellCheckingEnabled)
1818             document()->removeMarkers(DocumentMarker::Spelling);
1819         if (!isContinuousGrammarCheckingEnabled)
1820             document()->removeMarkers(DocumentMarker::Grammar);
1821     }
1822
1823     editor()->respondToChangedSelection(oldSelection);
1824 }
1825
1826 VisiblePosition Frame::visiblePositionForPoint(const IntPoint& framePoint)
1827 {
1828     HitTestResult result = eventHandler()->hitTestResultAtPoint(framePoint, true);
1829     Node* node = result.innerNode();
1830     if (!node)
1831         return VisiblePosition();
1832     RenderObject* renderer = node->renderer();
1833     if (!renderer)
1834         return VisiblePosition();
1835     VisiblePosition visiblePos = renderer->positionForCoordinates(result.localPoint().x(), result.localPoint().y());
1836     if (visiblePos.isNull())
1837         visiblePos = VisiblePosition(Position(node, 0));
1838     return visiblePos;
1839 }
1840     
1841 Document* Frame::documentAtPoint(const IntPoint& point)
1842 {  
1843     if (!view()) 
1844         return 0;
1845     
1846     IntPoint pt = view()->windowToContents(point);
1847     HitTestResult result = HitTestResult(pt);
1848     
1849     if (contentRenderer())
1850         result = eventHandler()->hitTestResultAtPoint(pt, false);
1851     return result.innerNode() ? result.innerNode()->document() : 0;
1852 }
1853     
1854 FramePrivate::FramePrivate(Page* page, Frame* parent, Frame* thisFrame, HTMLFrameOwnerElement* ownerElement,
1855                            FrameLoaderClient* frameLoaderClient)
1856     : m_page(page)
1857     , m_treeNode(thisFrame, parent)
1858     , m_loader(thisFrame, frameLoaderClient)
1859     , m_ownerElement(ownerElement)
1860     , m_script(thisFrame)
1861     , m_zoomFactor(parent ? parent->d->m_zoomFactor : 1.0f)
1862     , m_selectionGranularity(CharacterGranularity)
1863     , m_selectionController(thisFrame)
1864     , m_caretBlinkTimer(thisFrame, &Frame::caretBlinkTimerFired)
1865     , m_editor(thisFrame)
1866     , m_eventHandler(thisFrame)
1867     , m_animationController(thisFrame)
1868     , m_lifeSupportTimer(thisFrame, &Frame::lifeSupportTimerFired)
1869     , m_paintRestriction(PaintRestrictionNone)
1870     , m_caretVisible(false)
1871     , m_caretPaint(true)
1872     , m_isPainting(false)
1873     , m_highlightTextMatches(false)
1874     , m_inViewSourceMode(false)
1875     , m_prohibitsScrolling(false)
1876     , m_needsReapplyStyles(false)
1877     , m_isDisconnected(false)
1878 #if FRAME_LOADS_USER_STYLESHEET
1879     , m_userStyleSheetLoader(0)
1880 #endif
1881 {
1882 }
1883
1884 FramePrivate::~FramePrivate()
1885 {
1886 }
1887
1888 } // namespace WebCore