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