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