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