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