5c878b26df92222c601abeb24b57a331a520f867
[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, 2008, 2009, 2010 Apple Inc. All rights reserved.
9  * Copyright (C) 2005 Alexey Proskuryakov <ap@nypop.com>
10  * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
11  * Copyright (C) 2008 Eric Seidel <eric@webkit.org>
12  *
13  * This library is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU Library General Public
15  * License as published by the Free Software Foundation; either
16  * version 2 of the License, or (at your option) any later version.
17  *
18  * This library is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21  * Library General Public License for more details.
22  *
23  * You should have received a copy of the GNU Library General Public License
24  * along with this library; see the file COPYING.LIB.  If not, write to
25  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
26  * Boston, MA 02110-1301, USA.
27  */
28
29 #include "config.h"
30 #include "Frame.h"
31
32 #include "ApplyStyleCommand.h"
33 #include "CSSComputedStyleDeclaration.h"
34 #include "CSSMutableStyleDeclaration.h"
35 #include "CSSProperty.h"
36 #include "CSSPropertyNames.h"
37 #include "CachedCSSStyleSheet.h"
38 #include "Chrome.h"
39 #include "ChromeClient.h"
40 #include "DOMWindow.h"
41 #include "DocLoader.h"
42 #include "DocumentType.h"
43 #include "EditingText.h"
44 #include "EditorClient.h"
45 #include "EventNames.h"
46 #include "FloatQuad.h"
47 #include "FocusController.h"
48 #include "FrameLoader.h"
49 #include "FrameLoaderClient.h"
50 #include "FrameView.h"
51 #include "GraphicsContext.h"
52 #include "GraphicsLayer.h"
53 #include "HTMLDocument.h"
54 #include "HTMLFormControlElement.h"
55 #include "HTMLFormElement.h"
56 #include "HTMLFrameElementBase.h"
57 #include "HTMLNames.h"
58 #include "HTMLTableCellElement.h"
59 #include "HitTestResult.h"
60 #include "Logging.h"
61 #include "MediaFeatureNames.h"
62 #include "Navigator.h"
63 #include "NodeList.h"
64 #include "Page.h"
65 #include "PageGroup.h"
66 #include "RegularExpression.h"
67 #include "RenderLayer.h"
68 #include "RenderPart.h"
69 #include "RenderTableCell.h"
70 #include "RenderTextControl.h"
71 #include "RenderTheme.h"
72 #include "RenderView.h"
73 #include "ScriptController.h"
74 #include "ScriptSourceCode.h"
75 #include "ScriptValue.h"
76 #include "Settings.h"
77 #include "TextIterator.h"
78 #include "TextResourceDecoder.h"
79 #include "UserContentURLPattern.h"
80 #include "XMLNSNames.h"
81 #include "XMLNames.h"
82 #include "htmlediting.h"
83 #include "markup.h"
84 #include "npruntime_impl.h"
85 #include "visible_units.h"
86 #include <wtf/RefCountedLeakCounter.h>
87 #include <wtf/StdLibExtras.h>
88
89 #if USE(ACCELERATED_COMPOSITING)
90 #include "RenderLayerCompositor.h"
91 #endif
92
93 #if USE(JSC)
94 #include "JSDOMWindowShell.h"
95 #include "runtime_root.h"
96 #endif
97
98 #if ENABLE(MATHML)
99 #include "MathMLNames.h"
100 #endif
101
102 #if ENABLE(SVG)
103 #include "SVGDocument.h"
104 #include "SVGDocumentExtensions.h"
105 #include "SVGNames.h"
106 #include "XLinkNames.h"
107 #endif
108
109 #if ENABLE(TILED_BACKING_STORE)
110 #include "TiledBackingStore.h"
111 #endif
112
113 #if ENABLE(WML)
114 #include "WMLNames.h"
115 #endif
116
117 using namespace std;
118
119 namespace WebCore {
120
121 using namespace HTMLNames;
122
123 #ifndef NDEBUG
124 static WTF::RefCountedLeakCounter frameCounter("Frame");
125 #endif
126
127 static inline Frame* parentFromOwnerElement(HTMLFrameOwnerElement* ownerElement)
128 {
129     if (!ownerElement)
130         return 0;
131     return ownerElement->document()->frame();
132 }
133
134 inline Frame::Frame(Page* page, HTMLFrameOwnerElement* ownerElement, FrameLoaderClient* frameLoaderClient)
135     : m_page(page)
136     , m_treeNode(this, parentFromOwnerElement(ownerElement))
137     , m_loader(this, frameLoaderClient)
138     , m_redirectScheduler(this)
139     , m_ownerElement(ownerElement)
140     , m_script(this)
141     , m_editor(this)
142     , m_selectionController(this)
143     , m_eventHandler(this)
144     , m_animationController(this)
145     , m_lifeSupportTimer(this, &Frame::lifeSupportTimerFired)
146 #if ENABLE(ORIENTATION_EVENTS)
147     , m_orientation(0)
148 #endif
149     , m_highlightTextMatches(false)
150     , m_inViewSourceMode(false)
151     , m_needsReapplyStyles(false)
152     , m_isDisconnected(false)
153     , m_excludeFromTextSearch(false)
154 {
155     ASSERT(page);
156     AtomicString::init();
157     HTMLNames::init();
158     QualifiedName::init();
159     MediaFeatureNames::init();
160
161 #if ENABLE(SVG)
162     SVGNames::init();
163     XLinkNames::init();
164 #endif
165
166 #if ENABLE(WML)
167     WMLNames::init();
168 #endif
169
170 #if ENABLE(MATHML)
171     MathMLNames::init();
172 #endif
173
174     XMLNSNames::init();
175     XMLNames::init();
176
177     if (!ownerElement) {
178 #if ENABLE(TILED_BACKING_STORE)
179         // Top level frame only for now.
180         setTiledBackingStoreEnabled(page->settings()->tiledBackingStoreEnabled());
181 #endif
182     } else {
183         page->incrementFrameCount();
184
185         // Make sure we will not end up with two frames referencing the same owner element.
186         Frame*& contentFrameSlot = ownerElement->m_contentFrame;
187         ASSERT(!contentFrameSlot || contentFrameSlot->ownerElement() != ownerElement);
188         contentFrameSlot = this;
189     }
190
191 #ifndef NDEBUG
192     frameCounter.increment();
193 #endif
194 }
195
196 PassRefPtr<Frame> Frame::create(Page* page, HTMLFrameOwnerElement* ownerElement, FrameLoaderClient* client)
197 {
198     RefPtr<Frame> frame = adoptRef(new Frame(page, ownerElement, client));
199     if (!ownerElement)
200         page->setMainFrame(frame);
201     return frame.release();
202 }
203
204 Frame::~Frame()
205 {
206     setView(0);
207     loader()->cancelAndClear();
208
209     // FIXME: We should not be doing all this work inside the destructor
210
211     ASSERT(!m_lifeSupportTimer.isActive());
212
213 #ifndef NDEBUG
214     frameCounter.decrement();
215 #endif
216
217     disconnectOwnerElement();
218
219     if (m_domWindow)
220         m_domWindow->disconnectFrame();
221     script()->clearWindowShell();
222
223     HashSet<DOMWindow*>::iterator end = m_liveFormerWindows.end();
224     for (HashSet<DOMWindow*>::iterator it = m_liveFormerWindows.begin(); it != end; ++it)
225         (*it)->disconnectFrame();
226
227     if (m_view) {
228         m_view->hide();
229         m_view->clearFrame();
230     }
231
232     ASSERT(!m_lifeSupportTimer.isActive());
233 }
234
235 void Frame::setView(PassRefPtr<FrameView> view)
236 {
237     // We the custom scroll bars as early as possible to prevent m_doc->detach()
238     // from messing with the view such that its scroll bars won't be torn down.
239     // FIXME: We should revisit this.
240     if (m_view)
241         m_view->detachCustomScrollbars();
242
243     // Detach the document now, so any onUnload handlers get run - if
244     // we wait until the view is destroyed, then things won't be
245     // hooked up enough for some JavaScript calls to work.
246     if (!view && m_doc && m_doc->attached() && !m_doc->inPageCache()) {
247         // FIXME: We don't call willRemove here. Why is that OK?
248         m_doc->detach();
249         if (m_view)
250             m_view->unscheduleRelayout();
251     }
252     eventHandler()->clear();
253
254     m_view = view;
255
256     // Only one form submission is allowed per view of a part.
257     // Since this part may be getting reused as a result of being
258     // pulled from the back/forward cache, reset this flag.
259     loader()->resetMultipleFormSubmissionProtection();
260     
261 #if ENABLE(TILED_BACKING_STORE)
262     if (m_view && tiledBackingStore())
263         m_view->setPaintsEntireContents(true);
264 #endif
265 }
266
267 void Frame::setDocument(PassRefPtr<Document> newDoc)
268 {
269     if (m_doc && m_doc->attached() && !m_doc->inPageCache()) {
270         // FIXME: We don't call willRemove here. Why is that OK?
271         m_doc->detach();
272     }
273
274     m_doc = newDoc;
275     selection()->updateSecureKeyboardEntryIfActive();
276
277     if (m_doc && !m_doc->attached())
278         m_doc->attach();
279
280     // Update the cached 'document' property, which is now stale.
281     m_script.updateDocument();
282 }
283
284 #if ENABLE(ORIENTATION_EVENTS)
285 void Frame::sendOrientationChangeEvent(int orientation)
286 {
287     m_orientation = orientation;
288     if (Document* doc = document())
289         doc->dispatchWindowEvent(Event::create(eventNames().orientationchangeEvent, false, false));
290 }
291 #endif // ENABLE(ORIENTATION_EVENTS)
292     
293 Settings* Frame::settings() const
294 {
295     return m_page ? m_page->settings() : 0;
296 }
297
298 String Frame::selectedText() const
299 {
300     return plainText(selection()->toNormalizedRange().get());
301 }
302
303 IntRect Frame::firstRectForRange(Range* range) const
304 {
305     int extraWidthToEndOfLine = 0;
306     ExceptionCode ec = 0;
307     ASSERT(range->startContainer(ec));
308     ASSERT(range->endContainer(ec));
309
310     InlineBox* startInlineBox;
311     int startCaretOffset;
312     range->startPosition().getInlineBoxAndOffset(DOWNSTREAM, startInlineBox, startCaretOffset);
313
314     RenderObject* startRenderer = range->startContainer(ec)->renderer();
315     IntRect startCaretRect = startRenderer->localCaretRect(startInlineBox, startCaretOffset, &extraWidthToEndOfLine);
316     if (startCaretRect != IntRect())
317         startCaretRect = startRenderer->localToAbsoluteQuad(FloatRect(startCaretRect)).enclosingBoundingBox();
318
319     InlineBox* endInlineBox;
320     int endCaretOffset;
321     range->endPosition().getInlineBoxAndOffset(UPSTREAM, endInlineBox, endCaretOffset);
322
323     RenderObject* endRenderer = range->endContainer(ec)->renderer();
324     IntRect endCaretRect = endRenderer->localCaretRect(endInlineBox, endCaretOffset);
325     if (endCaretRect != IntRect())
326         endCaretRect = endRenderer->localToAbsoluteQuad(FloatRect(endCaretRect)).enclosingBoundingBox();
327
328     if (startCaretRect.y() == endCaretRect.y()) {
329         // start and end are on the same line
330         return IntRect(min(startCaretRect.x(), endCaretRect.x()),
331                        startCaretRect.y(),
332                        abs(endCaretRect.x() - startCaretRect.x()),
333                        max(startCaretRect.height(), endCaretRect.height()));
334     }
335
336     // start and end aren't on the same line, so go from start to the end of its line
337     return IntRect(startCaretRect.x(),
338                    startCaretRect.y(),
339                    startCaretRect.width() + extraWidthToEndOfLine,
340                    startCaretRect.height());
341 }
342
343 TextGranularity Frame::selectionGranularity() const
344 {
345     return m_selectionController.granularity();
346 }
347
348 SelectionController* Frame::dragCaretController() const
349 {
350     return m_page->dragCaretController();
351 }
352
353 static RegularExpression* createRegExpForLabels(const Vector<String>& labels)
354 {
355     // REVIEW- version of this call in FrameMac.mm caches based on the NSArray ptrs being
356     // the same across calls.  We can't do that.
357
358     DEFINE_STATIC_LOCAL(RegularExpression, wordRegExp, ("\\w", TextCaseSensitive));
359     String pattern("(");
360     unsigned int numLabels = labels.size();
361     unsigned int i;
362     for (i = 0; i < numLabels; i++) {
363         String label = labels[i];
364
365         bool startsWithWordChar = false;
366         bool endsWithWordChar = false;
367         if (label.length()) {
368             startsWithWordChar = wordRegExp.match(label.substring(0, 1)) >= 0;
369             endsWithWordChar = wordRegExp.match(label.substring(label.length() - 1, 1)) >= 0;
370         }
371
372         if (i)
373             pattern.append("|");
374         // Search for word boundaries only if label starts/ends with "word characters".
375         // If we always searched for word boundaries, this wouldn't work for languages
376         // such as Japanese.
377         if (startsWithWordChar)
378             pattern.append("\\b");
379         pattern.append(label);
380         if (endsWithWordChar)
381             pattern.append("\\b");
382     }
383     pattern.append(")");
384     return new RegularExpression(pattern, TextCaseInsensitive);
385 }
386
387 String Frame::searchForLabelsAboveCell(RegularExpression* regExp, HTMLTableCellElement* cell, size_t* resultDistanceFromStartOfCell)
388 {
389     RenderObject* cellRenderer = cell->renderer();
390
391     if (cellRenderer && cellRenderer->isTableCell()) {
392         RenderTableCell* tableCellRenderer = toRenderTableCell(cellRenderer);
393         RenderTableCell* cellAboveRenderer = tableCellRenderer->table()->cellAbove(tableCellRenderer);
394
395         if (cellAboveRenderer) {
396             HTMLTableCellElement* aboveCell =
397                 static_cast<HTMLTableCellElement*>(cellAboveRenderer->node());
398
399             if (aboveCell) {
400                 // search within the above cell we found for a match
401                 size_t lengthSearched = 0;    
402                 for (Node* n = aboveCell->firstChild(); n; n = n->traverseNextNode(aboveCell)) {
403                     if (n->isTextNode() && n->renderer() && n->renderer()->style()->visibility() == VISIBLE) {
404                         // For each text chunk, run the regexp
405                         String nodeString = n->nodeValue();
406                         int pos = regExp->searchRev(nodeString);
407                         if (pos >= 0) {
408                             if (resultDistanceFromStartOfCell)
409                                 *resultDistanceFromStartOfCell = lengthSearched;
410                             return nodeString.substring(pos, regExp->matchedLength());
411                         }
412                         lengthSearched += nodeString.length();
413                     }
414                 }
415             }
416         }
417     }
418     // Any reason in practice to search all cells in that are above cell?
419     if (resultDistanceFromStartOfCell)
420         *resultDistanceFromStartOfCell = notFound;
421     return String();
422 }
423
424 String Frame::searchForLabelsBeforeElement(const Vector<String>& labels, Element* element, size_t* resultDistance, bool* resultIsInCellAbove)
425 {
426     OwnPtr<RegularExpression> regExp(createRegExpForLabels(labels));
427     // We stop searching after we've seen this many chars
428     const unsigned int charsSearchedThreshold = 500;
429     // This is the absolute max we search.  We allow a little more slop than
430     // charsSearchedThreshold, to make it more likely that we'll search whole nodes.
431     const unsigned int maxCharsSearched = 600;
432     // If the starting element is within a table, the cell that contains it
433     HTMLTableCellElement* startingTableCell = 0;
434     bool searchedCellAbove = false;
435
436     if (resultDistance)
437         *resultDistance = notFound;
438     if (resultIsInCellAbove)
439         *resultIsInCellAbove = false;
440     
441     // walk backwards in the node tree, until another element, or form, or end of tree
442     int unsigned lengthSearched = 0;
443     Node* n;
444     for (n = element->traversePreviousNode();
445          n && lengthSearched < charsSearchedThreshold;
446          n = n->traversePreviousNode())
447     {
448         if (n->hasTagName(formTag)
449             || (n->isHTMLElement() && static_cast<Element*>(n)->isFormControlElement()))
450         {
451             // We hit another form element or the start of the form - bail out
452             break;
453         } else if (n->hasTagName(tdTag) && !startingTableCell) {
454             startingTableCell = static_cast<HTMLTableCellElement*>(n);
455         } else if (n->hasTagName(trTag) && startingTableCell) {
456             String result = searchForLabelsAboveCell(regExp.get(), startingTableCell, resultDistance);
457             if (!result.isEmpty()) {
458                 if (resultIsInCellAbove)
459                     *resultIsInCellAbove = true;
460                 return result;
461             }
462             searchedCellAbove = true;
463         } else if (n->isTextNode() && n->renderer() && n->renderer()->style()->visibility() == VISIBLE) {
464             // For each text chunk, run the regexp
465             String nodeString = n->nodeValue();
466             // add 100 for slop, to make it more likely that we'll search whole nodes
467             if (lengthSearched + nodeString.length() > maxCharsSearched)
468                 nodeString = nodeString.right(charsSearchedThreshold - lengthSearched);
469             int pos = regExp->searchRev(nodeString);
470             if (pos >= 0) {
471                 if (resultDistance)
472                     *resultDistance = lengthSearched;
473                 return nodeString.substring(pos, regExp->matchedLength());
474             }
475             lengthSearched += nodeString.length();
476         }
477     }
478
479     // If we started in a cell, but bailed because we found the start of the form or the
480     // previous element, we still might need to search the row above us for a label.
481     if (startingTableCell && !searchedCellAbove) {
482          String result = searchForLabelsAboveCell(regExp.get(), startingTableCell, resultDistance);
483         if (!result.isEmpty()) {
484             if (resultIsInCellAbove)
485                 *resultIsInCellAbove = true;
486             return result;
487         }
488     }
489     return String();
490 }
491
492 static String matchLabelsAgainstString(const Vector<String>& labels, const String& stringToMatch)
493 {
494     if (stringToMatch.isEmpty())
495         return String();
496
497     String mutableStringToMatch = stringToMatch;
498
499     // Make numbers and _'s in field names behave like word boundaries, e.g., "address2"
500     replace(mutableStringToMatch, RegularExpression("\\d", TextCaseSensitive), " ");
501     mutableStringToMatch.replace('_', ' ');
502     
503     OwnPtr<RegularExpression> regExp(createRegExpForLabels(labels));
504     // Use the largest match we can find in the whole string
505     int pos;
506     int length;
507     int bestPos = -1;
508     int bestLength = -1;
509     int start = 0;
510     do {
511         pos = regExp->match(mutableStringToMatch, start);
512         if (pos != -1) {
513             length = regExp->matchedLength();
514             if (length >= bestLength) {
515                 bestPos = pos;
516                 bestLength = length;
517             }
518             start = pos + 1;
519         }
520     } while (pos != -1);
521     
522     if (bestPos != -1)
523         return mutableStringToMatch.substring(bestPos, bestLength);
524     return String();
525 }
526     
527 String Frame::matchLabelsAgainstElement(const Vector<String>& labels, Element* element)
528 {
529     // Match against the name element, then against the id element if no match is found for the name element.
530     // See 7538330 for one popular site that benefits from the id element check.
531     // FIXME: This code is mirrored in FrameMac.mm. It would be nice to make the Mac code call the platform-agnostic
532     // code, which would require converting the NSArray of NSStrings to a Vector of Strings somewhere along the way.
533     String resultFromNameAttribute = matchLabelsAgainstString(labels, element->getAttribute(nameAttr));
534     if (!resultFromNameAttribute.isEmpty())
535         return resultFromNameAttribute;
536     
537     return matchLabelsAgainstString(labels, element->getAttribute(idAttr));
538 }
539
540 void Frame::notifyRendererOfSelectionChange(bool userTriggered)
541 {
542     RenderObject* renderer = 0;
543
544     document()->updateStyleIfNeeded();
545
546     if (selection()->rootEditableElement())
547         renderer = selection()->rootEditableElement()->shadowAncestorNode()->renderer();
548
549     // If the current selection is in a textfield or textarea, notify the renderer that the selection has changed
550     if (renderer && renderer->isTextControl())
551         toRenderTextControl(renderer)->selectionChanged(userTriggered);
552 }
553
554 // Helper function that tells whether a particular node is an element that has an entire
555 // Frame and FrameView, a <frame>, <iframe>, or <object>.
556 static bool isFrameElement(const Node *n)
557 {
558     if (!n)
559         return false;
560     RenderObject *renderer = n->renderer();
561     if (!renderer || !renderer->isWidget())
562         return false;
563     Widget* widget = toRenderWidget(renderer)->widget();
564     return widget && widget->isFrameView();
565 }
566
567 void Frame::setFocusedNodeIfNeeded()
568 {
569     if (selection()->isNone() || !selection()->isFocused())
570         return;
571
572     bool caretBrowsing = settings() && settings()->caretBrowsingEnabled();
573     if (caretBrowsing) {
574         Node* anchor = enclosingAnchorElement(selection()->base());
575         if (anchor) {
576             page()->focusController()->setFocusedNode(anchor, this);
577             return;
578         }
579     }
580
581     Node* target = selection()->rootEditableElement();
582     if (target) {
583         RenderObject* renderer = target->renderer();
584
585         // Walk up the render tree to search for a node to focus.
586         // Walking up the DOM tree wouldn't work for shadow trees, like those behind the engine-based text fields.
587         while (renderer) {
588             // We don't want to set focus on a subframe when selecting in a parent frame,
589             // so add the !isFrameElement check here. There's probably a better way to make this
590             // work in the long term, but this is the safest fix at this time.
591             if (target && target->isMouseFocusable() && !isFrameElement(target)) {
592                 page()->focusController()->setFocusedNode(target, this);
593                 return;
594             }
595             renderer = renderer->parent();
596             if (renderer)
597                 target = renderer->node();
598         }
599         document()->setFocusedNode(0);
600     }
601
602     if (caretBrowsing)
603         page()->focusController()->setFocusedNode(0, this);
604 }
605
606 void Frame::paintDragCaret(GraphicsContext* p, int tx, int ty, const IntRect& clipRect) const
607 {
608 #if ENABLE(TEXT_CARET)
609     SelectionController* dragCaretController = m_page->dragCaretController();
610     ASSERT(dragCaretController->selection().isCaret());
611     if (dragCaretController->selection().start().node()->document()->frame() == this)
612         dragCaretController->paintCaret(p, tx, ty, clipRect);
613 #else
614     UNUSED_PARAM(p);
615     UNUSED_PARAM(tx);
616     UNUSED_PARAM(ty);
617     UNUSED_PARAM(clipRect);
618 #endif
619 }
620
621 void Frame::setPrinting(bool printing, float minPageWidth, float maxPageWidth, bool adjustViewSize)
622 {
623     m_doc->setPrinting(printing);
624     view()->adjustMediaTypeForPrinting(printing);
625
626     m_doc->updateStyleSelector();
627     view()->forceLayoutWithPageWidthRange(minPageWidth, maxPageWidth, adjustViewSize);
628
629     for (Frame* child = tree()->firstChild(); child; child = child->tree()->nextSibling())
630         child->setPrinting(printing, minPageWidth, maxPageWidth, adjustViewSize);
631 }
632
633 void Frame::setNeedsReapplyStyles()
634 {
635     // When the frame is not showing web content, it doesn't make sense to apply styles.
636     // If we tried, we'd end up doing things with the document, but the document, if one
637     // exists, is not currently shown and should be in the page cache.
638     if (!m_loader.client()->hasHTMLView())
639         return;
640
641     if (m_needsReapplyStyles)
642         return;
643
644     m_needsReapplyStyles = true;
645
646     // FrameView's "layout" timer includes reapplyStyles, so despite its
647     // name, it's what we want to call here.
648     if (view())
649         view()->scheduleRelayout();
650 }
651
652 void Frame::reapplyStyles()
653 {
654     m_needsReapplyStyles = false;
655
656     // FIXME: This call doesn't really make sense in a function called reapplyStyles.
657     // We should probably eventually move it into its own function.
658     m_doc->docLoader()->setAutoLoadImages(m_page && m_page->settings()->loadsImagesAutomatically());
659
660     // FIXME: It's not entirely clear why the following is needed.
661     // The document automatically does this as required when you set the style sheet.
662     // But we had problems when this code was removed. Details are in
663     // <http://bugs.webkit.org/show_bug.cgi?id=8079>.
664     m_doc->updateStyleSelector();
665 }
666
667 void Frame::injectUserScripts(UserScriptInjectionTime injectionTime)
668 {
669     if (!m_page)
670         return;
671     
672     // Walk the hashtable. Inject by world.
673     const UserScriptMap* userScripts = m_page->group().userScripts();
674     if (!userScripts)
675         return;
676     UserScriptMap::const_iterator end = userScripts->end();
677     for (UserScriptMap::const_iterator it = userScripts->begin(); it != end; ++it)
678         injectUserScriptsForWorld(it->first.get(), *it->second, injectionTime);
679 }
680
681 void Frame::injectUserScriptsForWorld(DOMWrapperWorld* world, const UserScriptVector& userScripts, UserScriptInjectionTime injectionTime)
682 {
683     if (userScripts.isEmpty())
684         return;
685
686     Document* doc = document();
687     if (!doc)
688         return;
689
690     Vector<ScriptSourceCode> sourceCode;
691     unsigned count = userScripts.size();
692     for (unsigned i = 0; i < count; ++i) {
693         UserScript* script = userScripts[i].get();
694         if (script->injectedFrames() == InjectInTopFrameOnly && ownerElement())
695             continue;
696
697         if (script->injectionTime() == injectionTime && UserContentURLPattern::matchesPatterns(doc->url(), script->whitelist(), script->blacklist()))
698             m_script.evaluateInWorld(ScriptSourceCode(script->source(), script->url()), world);
699     }
700 }
701
702 bool Frame::shouldChangeSelection(const VisibleSelection& newSelection) const
703 {
704     return shouldChangeSelection(selection()->selection(), newSelection, newSelection.affinity(), false);
705 }
706
707 bool Frame::shouldChangeSelection(const VisibleSelection& oldSelection, const VisibleSelection& newSelection, EAffinity affinity, bool stillSelecting) const
708 {
709     return editor()->client()->shouldChangeSelectedRange(oldSelection.toNormalizedRange().get(), newSelection.toNormalizedRange().get(),
710                                                          affinity, stillSelecting);
711 }
712
713 bool Frame::shouldDeleteSelection(const VisibleSelection& selection) const
714 {
715     return editor()->client()->shouldDeleteRange(selection.toNormalizedRange().get());
716 }
717
718 bool Frame::isContentEditable() const
719 {
720     if (m_editor.clientIsEditable())
721         return true;
722     return m_doc->inDesignMode();
723 }
724
725 void Frame::setTypingStyle(CSSMutableStyleDeclaration *style)
726 {
727     m_typingStyle = style;
728 }
729
730 void Frame::computeAndSetTypingStyle(CSSStyleDeclaration *style, EditAction editingAction)
731 {
732     if (!style || !style->length()) {
733         clearTypingStyle();
734         return;
735     }
736
737     // Calculate the current typing style.
738     RefPtr<CSSMutableStyleDeclaration> mutableStyle = style->makeMutable();
739     if (typingStyle()) {
740         typingStyle()->merge(mutableStyle.get());
741         mutableStyle = typingStyle();
742     }
743
744     RefPtr<CSSValue> unicodeBidi;
745     RefPtr<CSSValue> direction;
746     if (editingAction == EditActionSetWritingDirection) {
747         unicodeBidi = mutableStyle->getPropertyCSSValue(CSSPropertyUnicodeBidi);
748         direction = mutableStyle->getPropertyCSSValue(CSSPropertyDirection);
749     }
750
751     Node* node = selection()->selection().visibleStart().deepEquivalent().node();
752     computedStyle(node)->diff(mutableStyle.get());
753
754     if (editingAction == EditActionSetWritingDirection && unicodeBidi) {
755         ASSERT(unicodeBidi->isPrimitiveValue());
756         mutableStyle->setProperty(CSSPropertyUnicodeBidi, static_cast<CSSPrimitiveValue*>(unicodeBidi.get())->getIdent());
757         if (direction) {
758             ASSERT(direction->isPrimitiveValue());
759             mutableStyle->setProperty(CSSPropertyDirection, static_cast<CSSPrimitiveValue*>(direction.get())->getIdent());
760         }
761     }
762
763     // Handle block styles, substracting these from the typing style.
764     RefPtr<CSSMutableStyleDeclaration> blockStyle = mutableStyle->copyBlockProperties();
765     blockStyle->diff(mutableStyle.get());
766     if (blockStyle->length() > 0)
767         applyCommand(ApplyStyleCommand::create(document(), blockStyle.get(), editingAction));
768
769     // Set the remaining style as the typing style.
770     m_typingStyle = mutableStyle.release();
771 }
772
773 String Frame::selectionStartStylePropertyValue(int stylePropertyID) const
774 {
775     Node *nodeToRemove;
776     RefPtr<CSSStyleDeclaration> selectionStyle = selectionComputedStyle(nodeToRemove);
777     if (!selectionStyle)
778         return String();
779
780     String value = selectionStyle->getPropertyValue(stylePropertyID);
781
782     if (nodeToRemove) {
783         ExceptionCode ec = 0;
784         nodeToRemove->remove(ec);
785         ASSERT(!ec);
786     }
787
788     return value;
789 }
790
791 PassRefPtr<CSSComputedStyleDeclaration> Frame::selectionComputedStyle(Node*& nodeToRemove) const
792 {
793     nodeToRemove = 0;
794
795     if (selection()->isNone())
796         return 0;
797
798     RefPtr<Range> range(selection()->toNormalizedRange());
799     Position pos = range->editingStartPosition();
800
801     Element *elem = pos.element();
802     if (!elem)
803         return 0;
804
805     RefPtr<Element> styleElement = elem;
806     ExceptionCode ec = 0;
807
808     if (m_typingStyle) {
809         styleElement = document()->createElement(spanTag, false);
810
811         styleElement->setAttribute(styleAttr, m_typingStyle->cssText().impl(), ec);
812         ASSERT(!ec);
813
814         styleElement->appendChild(document()->createEditingTextNode(""), ec);
815         ASSERT(!ec);
816
817         if (elem->renderer() && elem->renderer()->canHaveChildren()) {
818             elem->appendChild(styleElement, ec);
819         } else {
820             Node *parent = elem->parent();
821             Node *next = elem->nextSibling();
822
823             if (next)
824                 parent->insertBefore(styleElement, next, ec);
825             else
826                 parent->appendChild(styleElement, ec);
827         }
828         ASSERT(!ec);
829
830         nodeToRemove = styleElement.get();
831     }
832
833     return computedStyle(styleElement.release());
834 }
835
836 void Frame::textFieldDidBeginEditing(Element* e)
837 {
838     if (editor()->client())
839         editor()->client()->textFieldDidBeginEditing(e);
840 }
841
842 void Frame::textFieldDidEndEditing(Element* e)
843 {
844     if (editor()->client())
845         editor()->client()->textFieldDidEndEditing(e);
846 }
847
848 void Frame::textDidChangeInTextField(Element* e)
849 {
850     if (editor()->client())
851         editor()->client()->textDidChangeInTextField(e);
852 }
853
854 bool Frame::doTextFieldCommandFromEvent(Element* e, KeyboardEvent* ke)
855 {
856     if (editor()->client())
857         return editor()->client()->doTextFieldCommandFromEvent(e, ke);
858
859     return false;
860 }
861
862 void Frame::textWillBeDeletedInTextField(Element* input)
863 {
864     if (editor()->client())
865         editor()->client()->textWillBeDeletedInTextField(input);
866 }
867
868 void Frame::textDidChangeInTextArea(Element* e)
869 {
870     if (editor()->client())
871         editor()->client()->textDidChangeInTextArea(e);
872 }
873
874 void Frame::applyEditingStyleToBodyElement() const
875 {
876     RefPtr<NodeList> list = m_doc->getElementsByTagName("body");
877     unsigned len = list->length();
878     for (unsigned i = 0; i < len; i++)
879         applyEditingStyleToElement(static_cast<Element*>(list->item(i)));
880 }
881
882 void Frame::applyEditingStyleToElement(Element* element) const
883 {
884     if (!element)
885         return;
886
887     CSSStyleDeclaration* style = element->style();
888     ASSERT(style);
889
890     ExceptionCode ec = 0;
891     style->setProperty(CSSPropertyWordWrap, "break-word", false, ec);
892     ASSERT(!ec);
893     style->setProperty(CSSPropertyWebkitNbspMode, "space", false, ec);
894     ASSERT(!ec);
895     style->setProperty(CSSPropertyWebkitLineBreak, "after-white-space", false, ec);
896     ASSERT(!ec);
897 }
898
899 #ifndef NDEBUG
900 static HashSet<Frame*>& keepAliveSet()
901 {
902     DEFINE_STATIC_LOCAL(HashSet<Frame*>, staticKeepAliveSet, ());
903     return staticKeepAliveSet;
904 }
905 #endif
906
907 void Frame::keepAlive()
908 {
909     if (m_lifeSupportTimer.isActive())
910         return;
911 #ifndef NDEBUG
912     keepAliveSet().add(this);
913 #endif
914     ref();
915     m_lifeSupportTimer.startOneShot(0);
916 }
917
918 #ifndef NDEBUG
919 void Frame::cancelAllKeepAlive()
920 {
921     HashSet<Frame*>::iterator end = keepAliveSet().end();
922     for (HashSet<Frame*>::iterator it = keepAliveSet().begin(); it != end; ++it) {
923         Frame* frame = *it;
924         frame->m_lifeSupportTimer.stop();
925         frame->deref();
926     }
927     keepAliveSet().clear();
928 }
929 #endif
930
931 void Frame::lifeSupportTimerFired(Timer<Frame>*)
932 {
933 #ifndef NDEBUG
934     keepAliveSet().remove(this);
935 #endif
936     deref();
937 }
938
939 void Frame::clearDOMWindow()
940 {
941     if (m_domWindow) {
942         m_liveFormerWindows.add(m_domWindow.get());
943         m_domWindow->clear();
944     }
945     m_domWindow = 0;
946 }
947
948 RenderView* Frame::contentRenderer() const
949 {
950     Document* doc = document();
951     if (!doc)
952         return 0;
953     RenderObject* object = doc->renderer();
954     if (!object)
955         return 0;
956     ASSERT(object->isRenderView());
957     return toRenderView(object);
958 }
959
960 RenderPart* Frame::ownerRenderer() const
961 {
962     HTMLFrameOwnerElement* ownerElement = m_ownerElement;
963     if (!ownerElement)
964         return 0;
965     RenderObject* object = ownerElement->renderer();
966     if (!object)
967         return 0;
968     // FIXME: If <object> is ever fixed to disassociate itself from frames
969     // that it has started but canceled, then this can turn into an ASSERT
970     // since m_ownerElement would be 0 when the load is canceled.
971     // https://bugs.webkit.org/show_bug.cgi?id=18585
972     if (!object->isRenderPart())
973         return 0;
974     return toRenderPart(object);
975 }
976
977 // returns FloatRect because going through IntRect would truncate any floats
978 FloatRect Frame::selectionBounds(bool clipToVisibleContent) const
979 {
980     RenderView* root = contentRenderer();
981     FrameView* view = m_view.get();
982     if (!root || !view)
983         return IntRect();
984
985     IntRect selectionRect = root->selectionBounds(clipToVisibleContent);
986     return clipToVisibleContent ? intersection(selectionRect, view->visibleContentRect()) : selectionRect;
987 }
988
989 void Frame::selectionTextRects(Vector<FloatRect>& rects, SelectionRectRespectTransforms respectTransforms, bool clipToVisibleContent) const
990 {
991     RenderView* root = contentRenderer();
992     if (!root)
993         return;
994
995     RefPtr<Range> selectedRange = selection()->toNormalizedRange();
996
997     FloatRect visibleContentRect = m_view->visibleContentRect();
998     
999     // FIMXE: we are appending empty rects to the list for those that fall outside visibleContentRect.
1000     // We may not want to do that.
1001     if (respectTransforms) {
1002         Vector<FloatQuad> quads;
1003         selectedRange->textQuads(quads, true);
1004
1005         unsigned size = quads.size();
1006         for (unsigned i = 0; i < size; ++i) {
1007             IntRect currRect = quads[i].enclosingBoundingBox();
1008             if (clipToVisibleContent)
1009                 rects.append(intersection(currRect, visibleContentRect));
1010             else
1011                 rects.append(currRect);
1012         }
1013     } else {
1014         Vector<IntRect> intRects;
1015         selectedRange->textRects(intRects, true);
1016
1017         unsigned size = intRects.size();
1018         for (unsigned i = 0; i < size; ++i) {
1019             if (clipToVisibleContent)
1020                 rects.append(intersection(intRects[i], visibleContentRect));
1021             else
1022                 rects.append(intRects[i]);
1023         }
1024     }
1025 }
1026
1027 // Scans logically forward from "start", including any child frames
1028 static HTMLFormElement *scanForForm(Node *start)
1029 {
1030     Node *n;
1031     for (n = start; n; n = n->traverseNextNode()) {
1032         if (n->hasTagName(formTag))
1033             return static_cast<HTMLFormElement*>(n);
1034         else if (n->isHTMLElement() && static_cast<Element*>(n)->isFormControlElement())
1035             return static_cast<HTMLFormControlElement*>(n)->form();
1036         else if (n->hasTagName(frameTag) || n->hasTagName(iframeTag)) {
1037             Node *childDoc = static_cast<HTMLFrameElementBase*>(n)->contentDocument();
1038             if (HTMLFormElement *frameResult = scanForForm(childDoc))
1039                 return frameResult;
1040         }
1041     }
1042     return 0;
1043 }
1044
1045 // We look for either the form containing the current focus, or for one immediately after it
1046 HTMLFormElement *Frame::currentForm() const
1047 {
1048     // start looking either at the active (first responder) node, or where the selection is
1049     Node *start = m_doc ? m_doc->focusedNode() : 0;
1050     if (!start)
1051         start = selection()->start().node();
1052
1053     // try walking up the node tree to find a form element
1054     Node *n;
1055     for (n = start; n; n = n->parentNode()) {
1056         if (n->hasTagName(formTag))
1057             return static_cast<HTMLFormElement*>(n);
1058         else if (n->isHTMLElement() && static_cast<Element*>(n)->isFormControlElement())
1059             return static_cast<HTMLFormControlElement*>(n)->form();
1060     }
1061
1062     // try walking forward in the node tree to find a form element
1063     return start ? scanForForm(start) : 0;
1064 }
1065
1066 void Frame::revealSelection(const ScrollAlignment& alignment, bool revealExtent)
1067 {
1068     IntRect rect;
1069
1070     switch (selection()->selectionType()) {
1071     case VisibleSelection::NoSelection:
1072         return;
1073     case VisibleSelection::CaretSelection:
1074         rect = selection()->absoluteCaretBounds();
1075         break;
1076     case VisibleSelection::RangeSelection:
1077         rect = revealExtent ? VisiblePosition(selection()->extent()).absoluteCaretBounds() : enclosingIntRect(selectionBounds(false));
1078         break;
1079     }
1080
1081     Position start = selection()->start();
1082     ASSERT(start.node());
1083     if (start.node() && start.node()->renderer()) {
1084         // FIXME: This code only handles scrolling the startContainer's layer, but
1085         // the selection rect could intersect more than just that.
1086         // See <rdar://problem/4799899>.
1087         if (RenderLayer* layer = start.node()->renderer()->enclosingLayer())
1088             layer->scrollRectToVisible(rect, false, alignment, alignment);
1089     }
1090 }
1091
1092 Frame* Frame::frameForWidget(const Widget* widget)
1093 {
1094     ASSERT_ARG(widget, widget);
1095
1096     if (RenderWidget* renderer = RenderWidget::find(widget))
1097         if (Node* node = renderer->node())
1098             return node->document()->frame();
1099
1100     // Assume all widgets are either a FrameView or owned by a RenderWidget.
1101     // FIXME: That assumption is not right for scroll bars!
1102     ASSERT(widget->isFrameView());
1103     return static_cast<const FrameView*>(widget)->frame();
1104 }
1105
1106 void Frame::clearTimers(FrameView *view, Document *document)
1107 {
1108     if (view) {
1109         view->unscheduleRelayout();
1110         if (view->frame()) {
1111             view->frame()->animation()->suspendAnimations(document);
1112             view->frame()->eventHandler()->stopAutoscrollTimer();
1113         }
1114     }
1115 }
1116
1117 void Frame::clearTimers()
1118 {
1119     clearTimers(m_view.get(), document());
1120 }
1121
1122 RenderStyle *Frame::styleForSelectionStart(Node *&nodeToRemove) const
1123 {
1124     nodeToRemove = 0;
1125
1126     if (selection()->isNone())
1127         return 0;
1128
1129     Position pos = selection()->selection().visibleStart().deepEquivalent();
1130     if (!pos.isCandidate())
1131         return 0;
1132     Node *node = pos.node();
1133     if (!node)
1134         return 0;
1135
1136     if (!m_typingStyle)
1137         return node->renderer()->style();
1138
1139     RefPtr<Element> styleElement = document()->createElement(spanTag, false);
1140
1141     ExceptionCode ec = 0;
1142     String styleText = m_typingStyle->cssText() + " display: inline";
1143     styleElement->setAttribute(styleAttr, styleText.impl(), ec);
1144     ASSERT(!ec);
1145
1146     styleElement->appendChild(document()->createEditingTextNode(""), ec);
1147     ASSERT(!ec);
1148
1149     node->parentNode()->appendChild(styleElement, ec);
1150     ASSERT(!ec);
1151
1152     nodeToRemove = styleElement.get();
1153     return styleElement->renderer() ? styleElement->renderer()->style() : 0;
1154 }
1155
1156 void Frame::setSelectionFromNone()
1157 {
1158     // Put a caret inside the body if the entire frame is editable (either the
1159     // entire WebView is editable or designMode is on for this document).
1160     Document *doc = document();
1161     bool caretBrowsing = settings() && settings()->caretBrowsingEnabled();
1162     if (!selection()->isNone() || !(isContentEditable() || caretBrowsing))
1163         return;
1164
1165     Node* node = doc->documentElement();
1166     while (node && !node->hasTagName(bodyTag))
1167         node = node->traverseNextNode();
1168     if (node)
1169         selection()->setSelection(VisibleSelection(Position(node, 0), DOWNSTREAM));
1170 }
1171
1172 // Searches from the beginning of the document if nothing is selected.
1173 bool Frame::findString(const String& target, bool forward, bool caseFlag, bool wrapFlag, bool startInSelection)
1174 {
1175     if (target.isEmpty())
1176         return false;
1177
1178     if (excludeFromTextSearch())
1179         return false;
1180
1181     // Start from an edge of the selection, if there's a selection that's not in shadow content. Which edge
1182     // is used depends on whether we're searching forward or backward, and whether startInSelection is set.
1183     RefPtr<Range> searchRange(rangeOfContents(document()));
1184     VisibleSelection selection = this->selection()->selection();
1185
1186     if (forward)
1187         setStart(searchRange.get(), startInSelection ? selection.visibleStart() : selection.visibleEnd());
1188     else
1189         setEnd(searchRange.get(), startInSelection ? selection.visibleEnd() : selection.visibleStart());
1190
1191     Node* shadowTreeRoot = selection.shadowTreeRootNode();
1192     if (shadowTreeRoot) {
1193         ExceptionCode ec = 0;
1194         if (forward)
1195             searchRange->setEnd(shadowTreeRoot, shadowTreeRoot->childNodeCount(), ec);
1196         else
1197             searchRange->setStart(shadowTreeRoot, 0, ec);
1198     }
1199
1200     RefPtr<Range> resultRange(findPlainText(searchRange.get(), target, forward, caseFlag));
1201     // If we started in the selection and the found range exactly matches the existing selection, find again.
1202     // Build a selection with the found range to remove collapsed whitespace.
1203     // Compare ranges instead of selection objects to ignore the way that the current selection was made.
1204     if (startInSelection && areRangesEqual(VisibleSelection(resultRange.get()).toNormalizedRange().get(), selection.toNormalizedRange().get())) {
1205         searchRange = rangeOfContents(document());
1206         if (forward)
1207             setStart(searchRange.get(), selection.visibleEnd());
1208         else
1209             setEnd(searchRange.get(), selection.visibleStart());
1210
1211         if (shadowTreeRoot) {
1212             ExceptionCode ec = 0;
1213             if (forward)
1214                 searchRange->setEnd(shadowTreeRoot, shadowTreeRoot->childNodeCount(), ec);
1215             else
1216                 searchRange->setStart(shadowTreeRoot, 0, ec);
1217         }
1218
1219         resultRange = findPlainText(searchRange.get(), target, forward, caseFlag);
1220     }
1221
1222     ExceptionCode exception = 0;
1223
1224     // If nothing was found in the shadow tree, search in main content following the shadow tree.
1225     if (resultRange->collapsed(exception) && shadowTreeRoot) {
1226         searchRange = rangeOfContents(document());
1227         if (forward)
1228             searchRange->setStartAfter(shadowTreeRoot->shadowParentNode(), exception);
1229         else
1230             searchRange->setEndBefore(shadowTreeRoot->shadowParentNode(), exception);
1231
1232         resultRange = findPlainText(searchRange.get(), target, forward, caseFlag);
1233     }
1234
1235     if (!editor()->insideVisibleArea(resultRange.get())) {
1236         resultRange = editor()->nextVisibleRange(resultRange.get(), target, forward, caseFlag, wrapFlag);
1237         if (!resultRange)
1238             return false;
1239     }
1240
1241     // If we didn't find anything and we're wrapping, search again in the entire document (this will
1242     // redundantly re-search the area already searched in some cases).
1243     if (resultRange->collapsed(exception) && wrapFlag) {
1244         searchRange = rangeOfContents(document());
1245         resultRange = findPlainText(searchRange.get(), target, forward, caseFlag);
1246         // We used to return false here if we ended up with the same range that we started with
1247         // (e.g., the selection was already the only instance of this text). But we decided that
1248         // this should be a success case instead, so we'll just fall through in that case.
1249     }
1250
1251     if (resultRange->collapsed(exception))
1252         return false;
1253
1254     this->selection()->setSelection(VisibleSelection(resultRange.get(), DOWNSTREAM));
1255     revealSelection();
1256     return true;
1257 }
1258
1259 unsigned Frame::markAllMatchesForText(const String& target, bool caseFlag, unsigned limit)
1260 {
1261     if (target.isEmpty())
1262         return 0;
1263
1264     RefPtr<Range> searchRange(rangeOfContents(document()));
1265
1266     ExceptionCode exception = 0;
1267     unsigned matchCount = 0;
1268     do {
1269         RefPtr<Range> resultRange(findPlainText(searchRange.get(), target, true, caseFlag));
1270         if (resultRange->collapsed(exception)) {
1271             if (!resultRange->startContainer()->isInShadowTree())
1272                 break;
1273
1274             searchRange = rangeOfContents(document());
1275             searchRange->setStartAfter(resultRange->startContainer()->shadowAncestorNode(), exception);
1276             continue;
1277         }
1278
1279         // Only treat the result as a match if it is visible
1280         if (editor()->insideVisibleArea(resultRange.get())) {
1281             ++matchCount;
1282             document()->addMarker(resultRange.get(), DocumentMarker::TextMatch);
1283         }
1284
1285         // Stop looking if we hit the specified limit. A limit of 0 means no limit.
1286         if (limit > 0 && matchCount >= limit)
1287             break;
1288
1289         // Set the new start for the search range to be the end of the previous
1290         // result range. There is no need to use a VisiblePosition here,
1291         // since findPlainText will use a TextIterator to go over the visible
1292         // text nodes. 
1293         searchRange->setStart(resultRange->endContainer(exception), resultRange->endOffset(exception), exception);
1294
1295         Node* shadowTreeRoot = searchRange->shadowTreeRootNode();
1296         if (searchRange->collapsed(exception) && shadowTreeRoot)
1297             searchRange->setEnd(shadowTreeRoot, shadowTreeRoot->childNodeCount(), exception);
1298     } while (true);
1299
1300     // Do a "fake" paint in order to execute the code that computes the rendered rect for
1301     // each text match.
1302     Document* doc = document();
1303     if (m_view && contentRenderer()) {
1304         doc->updateLayout(); // Ensure layout is up to date.
1305         IntRect visibleRect = m_view->visibleContentRect();
1306         if (!visibleRect.isEmpty()) {
1307             GraphicsContext context((PlatformGraphicsContext*)0);
1308             context.setPaintingDisabled(true);
1309             m_view->paintContents(&context, visibleRect);
1310         }
1311     }
1312
1313     return matchCount;
1314 }
1315
1316 void Frame::setMarkedTextMatchesAreHighlighted(bool flag)
1317 {
1318     if (flag == m_highlightTextMatches)
1319         return;
1320
1321     m_highlightTextMatches = flag;
1322     document()->repaintMarkers(DocumentMarker::TextMatch);
1323 }
1324
1325 void Frame::setDOMWindow(DOMWindow* domWindow)
1326 {
1327     if (m_domWindow) {
1328         m_liveFormerWindows.add(m_domWindow.get());
1329         m_domWindow->clear();
1330     }
1331     m_domWindow = domWindow;
1332 }
1333
1334 DOMWindow* Frame::domWindow() const
1335 {
1336     if (!m_domWindow)
1337         m_domWindow = DOMWindow::create(const_cast<Frame*>(this));
1338
1339     return m_domWindow.get();
1340 }
1341
1342 void Frame::clearFormerDOMWindow(DOMWindow* window)
1343 {
1344     m_liveFormerWindows.remove(window);
1345 }
1346
1347 void Frame::pageDestroyed()
1348 {
1349     if (Frame* parent = tree()->parent())
1350         parent->loader()->checkLoadComplete();
1351
1352     // FIXME: It's unclear as to why this is called more than once, but it is,
1353     // so page() could be NULL.
1354     if (page() && page()->focusController()->focusedFrame() == this)
1355         page()->focusController()->setFocusedFrame(0);
1356
1357     script()->clearWindowShell();
1358     script()->clearScriptObjects();
1359     script()->updatePlatformScriptObjects();
1360
1361     detachFromPage();
1362 }
1363
1364 void Frame::disconnectOwnerElement()
1365 {
1366     if (m_ownerElement) {
1367         if (Document* doc = document())
1368             doc->clearAXObjectCache();
1369         m_ownerElement->m_contentFrame = 0;
1370         if (m_page)
1371             m_page->decrementFrameCount();
1372     }
1373     m_ownerElement = 0;
1374 }
1375
1376 // The frame is moved in DOM, potentially to another page.
1377 void Frame::transferChildFrameToNewDocument()
1378 {
1379     ASSERT(m_ownerElement);
1380     Frame* newParent = m_ownerElement->document()->frame();
1381     bool didTransfer = false;
1382
1383     // Switch page.
1384     Page* newPage = newParent ? newParent->page() : 0;
1385     if (m_page != newPage) {
1386         if (page()->focusController()->focusedFrame() == this)
1387             page()->focusController()->setFocusedFrame(0);
1388
1389         if (m_page)
1390             m_page->decrementFrameCount();
1391
1392         m_page = newPage;
1393
1394         if (newPage)
1395             newPage->incrementFrameCount();
1396
1397         didTransfer = true;
1398     }
1399
1400     // Update the frame tree.
1401     Frame* oldParent = tree()->parent();
1402     if (oldParent != newParent) {
1403         if (oldParent)
1404             oldParent->tree()->removeChild(this);
1405         if (newParent) {
1406             newParent->tree()->appendChild(this);
1407             m_ownerElement->setName();
1408         }
1409         didTransfer = true;
1410     }
1411
1412     // Avoid unnecessary calls to client and frame subtree if the frame ended
1413     // up on the same page and under the same parent frame.
1414     if (didTransfer) {
1415         // Let external clients update themselves.
1416         loader()->client()->didTransferChildFrameToNewDocument();
1417
1418         // Do the same for all the children.
1419         for (Frame* child = tree()->firstChild(); child; child = child->tree()->nextSibling())
1420             child->transferChildFrameToNewDocument();
1421     }
1422 }
1423
1424 String Frame::documentTypeString() const
1425 {
1426     if (DocumentType* doctype = document()->doctype())
1427         return createMarkup(doctype);
1428
1429     return String();
1430 }
1431
1432 void Frame::respondToChangedSelection(const VisibleSelection& oldSelection, bool closeTyping)
1433 {
1434     bool isContinuousSpellCheckingEnabled = editor()->isContinuousSpellCheckingEnabled();
1435     bool isContinuousGrammarCheckingEnabled = isContinuousSpellCheckingEnabled && editor()->isGrammarCheckingEnabled();
1436     if (isContinuousSpellCheckingEnabled) {
1437         VisibleSelection newAdjacentWords;
1438         VisibleSelection newSelectedSentence;
1439         bool caretBrowsing = settings() && settings()->caretBrowsingEnabled();
1440         if (selection()->selection().isContentEditable() || caretBrowsing) {
1441             VisiblePosition newStart(selection()->selection().visibleStart());
1442             newAdjacentWords = VisibleSelection(startOfWord(newStart, LeftWordIfOnBoundary), endOfWord(newStart, RightWordIfOnBoundary));
1443             if (isContinuousGrammarCheckingEnabled)
1444                 newSelectedSentence = VisibleSelection(startOfSentence(newStart), endOfSentence(newStart));
1445         }
1446
1447         // When typing we check spelling elsewhere, so don't redo it here.
1448         // If this is a change in selection resulting from a delete operation,
1449         // oldSelection may no longer be in the document.
1450         if (closeTyping && oldSelection.isContentEditable() && oldSelection.start().node() && oldSelection.start().node()->inDocument()) {
1451             VisiblePosition oldStart(oldSelection.visibleStart());
1452             VisibleSelection oldAdjacentWords = VisibleSelection(startOfWord(oldStart, LeftWordIfOnBoundary), endOfWord(oldStart, RightWordIfOnBoundary));
1453             if (oldAdjacentWords != newAdjacentWords) {
1454                 if (isContinuousGrammarCheckingEnabled) {
1455                     VisibleSelection oldSelectedSentence = VisibleSelection(startOfSentence(oldStart), endOfSentence(oldStart));
1456                     editor()->markMisspellingsAndBadGrammar(oldAdjacentWords, oldSelectedSentence != newSelectedSentence, oldSelectedSentence);
1457                 } else
1458                     editor()->markMisspellingsAndBadGrammar(oldAdjacentWords, false, oldAdjacentWords);
1459             }
1460         }
1461
1462         // This only erases markers that are in the first unit (word or sentence) of the selection.
1463         // Perhaps peculiar, but it matches AppKit.
1464         if (RefPtr<Range> wordRange = newAdjacentWords.toNormalizedRange())
1465             document()->removeMarkers(wordRange.get(), DocumentMarker::Spelling);
1466         if (RefPtr<Range> sentenceRange = newSelectedSentence.toNormalizedRange())
1467             document()->removeMarkers(sentenceRange.get(), DocumentMarker::Grammar);
1468     }
1469
1470     // When continuous spell checking is off, existing markers disappear after the selection changes.
1471     if (!isContinuousSpellCheckingEnabled)
1472         document()->removeMarkers(DocumentMarker::Spelling);
1473     if (!isContinuousGrammarCheckingEnabled)
1474         document()->removeMarkers(DocumentMarker::Grammar);
1475
1476     editor()->respondToChangedSelection(oldSelection);
1477 }
1478
1479 VisiblePosition Frame::visiblePositionForPoint(const IntPoint& framePoint)
1480 {
1481     HitTestResult result = eventHandler()->hitTestResultAtPoint(framePoint, true);
1482     Node* node = result.innerNode();
1483     if (!node)
1484         return VisiblePosition();
1485     RenderObject* renderer = node->renderer();
1486     if (!renderer)
1487         return VisiblePosition();
1488     VisiblePosition visiblePos = renderer->positionForPoint(result.localPoint());
1489     if (visiblePos.isNull())
1490         visiblePos = VisiblePosition(Position(node, 0));
1491     return visiblePos;
1492 }
1493
1494 Document* Frame::documentAtPoint(const IntPoint& point)
1495 {
1496     if (!view())
1497         return 0;
1498
1499     IntPoint pt = view()->windowToContents(point);
1500     HitTestResult result = HitTestResult(pt);
1501
1502     if (contentRenderer())
1503         result = eventHandler()->hitTestResultAtPoint(pt, false);
1504     return result.innerNode() ? result.innerNode()->document() : 0;
1505 }
1506
1507 void Frame::createView(const IntSize& viewportSize,
1508                        const Color& backgroundColor, bool transparent,
1509                        const IntSize& fixedLayoutSize, bool useFixedLayout,
1510                        ScrollbarMode horizontalScrollbarMode, bool horizontalLock,
1511                        ScrollbarMode verticalScrollbarMode, bool verticalLock)
1512 {
1513     ASSERT(this);
1514     ASSERT(m_page);
1515
1516     bool isMainFrame = this == m_page->mainFrame();
1517
1518     if (isMainFrame && view())
1519         view()->setParentVisible(false);
1520
1521     setView(0);
1522
1523     RefPtr<FrameView> frameView;
1524     if (isMainFrame) {
1525         frameView = FrameView::create(this, viewportSize);
1526         frameView->setFixedLayoutSize(fixedLayoutSize);
1527         frameView->setUseFixedLayout(useFixedLayout);
1528     } else
1529         frameView = FrameView::create(this);
1530
1531     frameView->setScrollbarModes(horizontalScrollbarMode, verticalScrollbarMode, horizontalLock, verticalLock);
1532
1533     setView(frameView);
1534
1535     if (backgroundColor.isValid())
1536         frameView->updateBackgroundRecursively(backgroundColor, transparent);
1537
1538     if (isMainFrame)
1539         frameView->setParentVisible(true);
1540
1541     if (ownerRenderer())
1542         ownerRenderer()->setWidget(frameView);
1543
1544     if (HTMLFrameOwnerElement* owner = ownerElement())
1545         view()->setCanHaveScrollbars(owner->scrollingMode() != ScrollbarAlwaysOff);
1546 }
1547
1548 #if ENABLE(TILED_BACKING_STORE)
1549 void Frame::setTiledBackingStoreEnabled(bool enabled)
1550 {
1551     if (!enabled) {
1552         m_tiledBackingStore.clear();
1553         return;
1554     }
1555     if (m_tiledBackingStore)
1556         return;
1557     m_tiledBackingStore.set(new TiledBackingStore(this));
1558     if (m_view)
1559         m_view->setPaintsEntireContents(true);
1560 }
1561
1562 void Frame::tiledBackingStorePaintBegin()
1563 {
1564     if (!m_view)
1565         return;
1566     m_view->layoutIfNeededRecursive();
1567     m_view->flushDeferredRepaints();
1568 }
1569
1570 void Frame::tiledBackingStorePaint(GraphicsContext* context, const IntRect& rect)
1571 {
1572     if (!m_view)
1573         return;
1574     m_view->paintContents(context, rect);
1575 }
1576
1577 void Frame::tiledBackingStorePaintEnd(const Vector<IntRect>& paintedArea)
1578 {
1579     if (!m_page || !m_view)
1580         return;
1581     unsigned size = paintedArea.size();
1582     // Request repaint from the system
1583     for (int n = 0; n < size; ++n)
1584         m_page->chrome()->invalidateContentsAndWindow(m_view->contentsToWindow(paintedArea[n]), false);
1585 }
1586
1587 IntRect Frame::tiledBackingStoreContentsRect()
1588 {
1589     if (!m_view)
1590         return IntRect();
1591     return IntRect(IntPoint(), m_view->contentsSize());
1592 }
1593
1594 IntRect Frame::tiledBackingStoreVisibleRect()
1595 {
1596     if (!m_page)
1597         return IntRect();
1598     return m_page->chrome()->client()->visibleRectForTiledBackingStore();
1599 }
1600 #endif
1601
1602 String Frame::layerTreeAsText() const
1603 {
1604 #if USE(ACCELERATED_COMPOSITING)
1605     document()->updateLayout();
1606
1607     if (!contentRenderer())
1608         return String();
1609
1610     GraphicsLayer* rootLayer = contentRenderer()->compositor()->rootPlatformLayer();
1611     if (!rootLayer)
1612         return String();
1613
1614     return rootLayer->layerTreeAsText();
1615 #else
1616     return String();
1617 #endif
1618 }
1619
1620 } // namespace WebCore