8c546ce8d8feb2491671c7fd16a592c292d49c9e
[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 "CachedResourceLoader.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 "Settings.h"
76 #include "TextIterator.h"
77 #include "TextResourceDecoder.h"
78 #include "UserContentURLPattern.h"
79 #include "UserTypingGestureIndicator.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_inViewSourceMode(false)
148     , m_isDisconnected(false)
149     , m_excludeFromTextSearch(false)
150 {
151     ASSERT(page);
152     AtomicString::init();
153     HTMLNames::init();
154     QualifiedName::init();
155     MediaFeatureNames::init();
156     SVGNames::init();
157     XLinkNames::init();
158     MathMLNames::init();
159     XMLNSNames::init();
160     XMLNames::init();
161
162 #if ENABLE(WML)
163     WMLNames::init();
164 #endif
165
166     if (!ownerElement) {
167 #if ENABLE(TILED_BACKING_STORE)
168         // Top level frame only for now.
169         setTiledBackingStoreEnabled(page->settings()->tiledBackingStoreEnabled());
170 #endif
171     } else {
172         page->incrementFrameCount();
173
174         // Make sure we will not end up with two frames referencing the same owner element.
175         Frame*& contentFrameSlot = ownerElement->m_contentFrame;
176         ASSERT(!contentFrameSlot || contentFrameSlot->ownerElement() != ownerElement);
177         contentFrameSlot = this;
178     }
179
180 #ifndef NDEBUG
181     frameCounter.increment();
182 #endif
183 }
184
185 PassRefPtr<Frame> Frame::create(Page* page, HTMLFrameOwnerElement* ownerElement, FrameLoaderClient* client)
186 {
187     RefPtr<Frame> frame = adoptRef(new Frame(page, ownerElement, client));
188     if (!ownerElement)
189         page->setMainFrame(frame);
190     return frame.release();
191 }
192
193 Frame::~Frame()
194 {
195     setView(0);
196     loader()->cancelAndClear();
197
198     // FIXME: We should not be doing all this work inside the destructor
199
200     ASSERT(!m_lifeSupportTimer.isActive());
201
202 #ifndef NDEBUG
203     frameCounter.decrement();
204 #endif
205
206     disconnectOwnerElement();
207
208     if (m_domWindow)
209         m_domWindow->disconnectFrame();
210     script()->clearWindowShell();
211
212     HashSet<DOMWindow*>::iterator end = m_liveFormerWindows.end();
213     for (HashSet<DOMWindow*>::iterator it = m_liveFormerWindows.begin(); it != end; ++it)
214         (*it)->disconnectFrame();
215
216     if (m_view) {
217         m_view->hide();
218         m_view->clearFrame();
219     }
220
221     ASSERT(!m_lifeSupportTimer.isActive());
222 }
223
224 void Frame::setView(PassRefPtr<FrameView> view)
225 {
226     // We the custom scroll bars as early as possible to prevent m_doc->detach()
227     // from messing with the view such that its scroll bars won't be torn down.
228     // FIXME: We should revisit this.
229     if (m_view)
230         m_view->detachCustomScrollbars();
231
232     // Detach the document now, so any onUnload handlers get run - if
233     // we wait until the view is destroyed, then things won't be
234     // hooked up enough for some JavaScript calls to work.
235     if (!view && m_doc && m_doc->attached() && !m_doc->inPageCache()) {
236         // FIXME: We don't call willRemove here. Why is that OK?
237         m_doc->detach();
238     }
239     
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 TextGranularity Frame::selectionGranularity() const
290 {
291     return m_selectionController.granularity();
292 }
293
294 SelectionController* Frame::dragCaretController() const
295 {
296     return m_page->dragCaretController();
297 }
298
299 static RegularExpression* createRegExpForLabels(const Vector<String>& labels)
300 {
301     // REVIEW- version of this call in FrameMac.mm caches based on the NSArray ptrs being
302     // the same across calls.  We can't do that.
303
304     DEFINE_STATIC_LOCAL(RegularExpression, wordRegExp, ("\\w", TextCaseSensitive));
305     String pattern("(");
306     unsigned int numLabels = labels.size();
307     unsigned int i;
308     for (i = 0; i < numLabels; i++) {
309         String label = labels[i];
310
311         bool startsWithWordChar = false;
312         bool endsWithWordChar = false;
313         if (label.length()) {
314             startsWithWordChar = wordRegExp.match(label.substring(0, 1)) >= 0;
315             endsWithWordChar = wordRegExp.match(label.substring(label.length() - 1, 1)) >= 0;
316         }
317
318         if (i)
319             pattern.append("|");
320         // Search for word boundaries only if label starts/ends with "word characters".
321         // If we always searched for word boundaries, this wouldn't work for languages
322         // such as Japanese.
323         if (startsWithWordChar)
324             pattern.append("\\b");
325         pattern.append(label);
326         if (endsWithWordChar)
327             pattern.append("\\b");
328     }
329     pattern.append(")");
330     return new RegularExpression(pattern, TextCaseInsensitive);
331 }
332
333 String Frame::searchForLabelsAboveCell(RegularExpression* regExp, HTMLTableCellElement* cell, size_t* resultDistanceFromStartOfCell)
334 {
335     RenderObject* cellRenderer = cell->renderer();
336
337     if (cellRenderer && cellRenderer->isTableCell()) {
338         RenderTableCell* tableCellRenderer = toRenderTableCell(cellRenderer);
339         RenderTableCell* cellAboveRenderer = tableCellRenderer->table()->cellAbove(tableCellRenderer);
340
341         if (cellAboveRenderer) {
342             HTMLTableCellElement* aboveCell =
343                 static_cast<HTMLTableCellElement*>(cellAboveRenderer->node());
344
345             if (aboveCell) {
346                 // search within the above cell we found for a match
347                 size_t lengthSearched = 0;    
348                 for (Node* n = aboveCell->firstChild(); n; n = n->traverseNextNode(aboveCell)) {
349                     if (n->isTextNode() && n->renderer() && n->renderer()->style()->visibility() == VISIBLE) {
350                         // For each text chunk, run the regexp
351                         String nodeString = n->nodeValue();
352                         int pos = regExp->searchRev(nodeString);
353                         if (pos >= 0) {
354                             if (resultDistanceFromStartOfCell)
355                                 *resultDistanceFromStartOfCell = lengthSearched;
356                             return nodeString.substring(pos, regExp->matchedLength());
357                         }
358                         lengthSearched += nodeString.length();
359                     }
360                 }
361             }
362         }
363     }
364     // Any reason in practice to search all cells in that are above cell?
365     if (resultDistanceFromStartOfCell)
366         *resultDistanceFromStartOfCell = notFound;
367     return String();
368 }
369
370 String Frame::searchForLabelsBeforeElement(const Vector<String>& labels, Element* element, size_t* resultDistance, bool* resultIsInCellAbove)
371 {
372     OwnPtr<RegularExpression> regExp(createRegExpForLabels(labels));
373     // We stop searching after we've seen this many chars
374     const unsigned int charsSearchedThreshold = 500;
375     // This is the absolute max we search.  We allow a little more slop than
376     // charsSearchedThreshold, to make it more likely that we'll search whole nodes.
377     const unsigned int maxCharsSearched = 600;
378     // If the starting element is within a table, the cell that contains it
379     HTMLTableCellElement* startingTableCell = 0;
380     bool searchedCellAbove = false;
381
382     if (resultDistance)
383         *resultDistance = notFound;
384     if (resultIsInCellAbove)
385         *resultIsInCellAbove = false;
386     
387     // walk backwards in the node tree, until another element, or form, or end of tree
388     int unsigned lengthSearched = 0;
389     Node* n;
390     for (n = element->traversePreviousNode();
391          n && lengthSearched < charsSearchedThreshold;
392          n = n->traversePreviousNode())
393     {
394         if (n->hasTagName(formTag)
395             || (n->isHTMLElement() && static_cast<Element*>(n)->isFormControlElement()))
396         {
397             // We hit another form element or the start of the form - bail out
398             break;
399         } else if (n->hasTagName(tdTag) && !startingTableCell) {
400             startingTableCell = static_cast<HTMLTableCellElement*>(n);
401         } else if (n->hasTagName(trTag) && startingTableCell) {
402             String result = searchForLabelsAboveCell(regExp.get(), startingTableCell, resultDistance);
403             if (!result.isEmpty()) {
404                 if (resultIsInCellAbove)
405                     *resultIsInCellAbove = true;
406                 return result;
407             }
408             searchedCellAbove = true;
409         } else if (n->isTextNode() && n->renderer() && n->renderer()->style()->visibility() == VISIBLE) {
410             // For each text chunk, run the regexp
411             String nodeString = n->nodeValue();
412             // add 100 for slop, to make it more likely that we'll search whole nodes
413             if (lengthSearched + nodeString.length() > maxCharsSearched)
414                 nodeString = nodeString.right(charsSearchedThreshold - lengthSearched);
415             int pos = regExp->searchRev(nodeString);
416             if (pos >= 0) {
417                 if (resultDistance)
418                     *resultDistance = lengthSearched;
419                 return nodeString.substring(pos, regExp->matchedLength());
420             }
421             lengthSearched += nodeString.length();
422         }
423     }
424
425     // If we started in a cell, but bailed because we found the start of the form or the
426     // previous element, we still might need to search the row above us for a label.
427     if (startingTableCell && !searchedCellAbove) {
428          String result = searchForLabelsAboveCell(regExp.get(), startingTableCell, resultDistance);
429         if (!result.isEmpty()) {
430             if (resultIsInCellAbove)
431                 *resultIsInCellAbove = true;
432             return result;
433         }
434     }
435     return String();
436 }
437
438 static String matchLabelsAgainstString(const Vector<String>& labels, const String& stringToMatch)
439 {
440     if (stringToMatch.isEmpty())
441         return String();
442
443     String mutableStringToMatch = stringToMatch;
444
445     // Make numbers and _'s in field names behave like word boundaries, e.g., "address2"
446     replace(mutableStringToMatch, RegularExpression("\\d", TextCaseSensitive), " ");
447     mutableStringToMatch.replace('_', ' ');
448     
449     OwnPtr<RegularExpression> regExp(createRegExpForLabels(labels));
450     // Use the largest match we can find in the whole string
451     int pos;
452     int length;
453     int bestPos = -1;
454     int bestLength = -1;
455     int start = 0;
456     do {
457         pos = regExp->match(mutableStringToMatch, start);
458         if (pos != -1) {
459             length = regExp->matchedLength();
460             if (length >= bestLength) {
461                 bestPos = pos;
462                 bestLength = length;
463             }
464             start = pos + 1;
465         }
466     } while (pos != -1);
467     
468     if (bestPos != -1)
469         return mutableStringToMatch.substring(bestPos, bestLength);
470     return String();
471 }
472     
473 String Frame::matchLabelsAgainstElement(const Vector<String>& labels, Element* element)
474 {
475     // Match against the name element, then against the id element if no match is found for the name element.
476     // See 7538330 for one popular site that benefits from the id element check.
477     // FIXME: This code is mirrored in FrameMac.mm. It would be nice to make the Mac code call the platform-agnostic
478     // code, which would require converting the NSArray of NSStrings to a Vector of Strings somewhere along the way.
479     String resultFromNameAttribute = matchLabelsAgainstString(labels, element->getAttribute(nameAttr));
480     if (!resultFromNameAttribute.isEmpty())
481         return resultFromNameAttribute;
482     
483     return matchLabelsAgainstString(labels, element->getAttribute(idAttr));
484 }
485
486 void Frame::notifyRendererOfSelectionChange(bool userTriggered)
487 {
488     RenderObject* renderer = 0;
489
490     document()->updateStyleIfNeeded();
491
492     if (selection()->rootEditableElement())
493         renderer = selection()->rootEditableElement()->shadowAncestorNode()->renderer();
494
495     // If the current selection is in a textfield or textarea, notify the renderer that the selection has changed
496     if (renderer && renderer->isTextControl())
497         toRenderTextControl(renderer)->selectionChanged(userTriggered);
498 }
499
500 // Helper function that tells whether a particular node is an element that has an entire
501 // Frame and FrameView, a <frame>, <iframe>, or <object>.
502 static bool isFrameElement(const Node *n)
503 {
504     if (!n)
505         return false;
506     RenderObject *renderer = n->renderer();
507     if (!renderer || !renderer->isWidget())
508         return false;
509     Widget* widget = toRenderWidget(renderer)->widget();
510     return widget && widget->isFrameView();
511 }
512
513 void Frame::setFocusedNodeIfNeeded()
514 {
515     if (selection()->isNone() || !selection()->isFocused())
516         return;
517
518     bool caretBrowsing = settings() && settings()->caretBrowsingEnabled();
519     if (caretBrowsing) {
520         Node* anchor = enclosingAnchorElement(selection()->base());
521         if (anchor) {
522             page()->focusController()->setFocusedNode(anchor, this);
523             return;
524         }
525     }
526
527     Node* target = selection()->rootEditableElement();
528     if (target) {
529         RenderObject* renderer = target->renderer();
530
531         // Walk up the render tree to search for a node to focus.
532         // Walking up the DOM tree wouldn't work for shadow trees, like those behind the engine-based text fields.
533         while (renderer) {
534             // We don't want to set focus on a subframe when selecting in a parent frame,
535             // so add the !isFrameElement check here. There's probably a better way to make this
536             // work in the long term, but this is the safest fix at this time.
537             if (target && target->isMouseFocusable() && !isFrameElement(target)) {
538                 page()->focusController()->setFocusedNode(target, this);
539                 return;
540             }
541             renderer = renderer->parent();
542             if (renderer)
543                 target = renderer->node();
544         }
545         document()->setFocusedNode(0);
546     }
547
548     if (caretBrowsing)
549         page()->focusController()->setFocusedNode(0, this);
550 }
551
552 void Frame::paintDragCaret(GraphicsContext* p, int tx, int ty, const IntRect& clipRect) const
553 {
554 #if ENABLE(TEXT_CARET)
555     SelectionController* dragCaretController = m_page->dragCaretController();
556     ASSERT(dragCaretController->selection().isCaret());
557     if (dragCaretController->selection().start().node()->document()->frame() == this)
558         dragCaretController->paintCaret(p, tx, ty, clipRect);
559 #else
560     UNUSED_PARAM(p);
561     UNUSED_PARAM(tx);
562     UNUSED_PARAM(ty);
563     UNUSED_PARAM(clipRect);
564 #endif
565 }
566
567 void Frame::setPrinting(bool printing, const FloatSize& pageSize, float maximumShrinkRatio, AdjustViewSizeOrNot shouldAdjustViewSize)
568 {
569     m_doc->setPrinting(printing);
570     view()->adjustMediaTypeForPrinting(printing);
571
572     m_doc->styleSelectorChanged(RecalcStyleImmediately);
573     view()->forceLayoutForPagination(pageSize, maximumShrinkRatio, shouldAdjustViewSize);
574
575     for (Frame* child = tree()->firstChild(); child; child = child->tree()->nextSibling())
576         child->setPrinting(printing, pageSize, maximumShrinkRatio, shouldAdjustViewSize);
577 }
578
579 void Frame::injectUserScripts(UserScriptInjectionTime injectionTime)
580 {
581     if (!m_page)
582         return;
583     
584     // Walk the hashtable. Inject by world.
585     const UserScriptMap* userScripts = m_page->group().userScripts();
586     if (!userScripts)
587         return;
588     UserScriptMap::const_iterator end = userScripts->end();
589     for (UserScriptMap::const_iterator it = userScripts->begin(); it != end; ++it)
590         injectUserScriptsForWorld(it->first.get(), *it->second, injectionTime);
591 }
592
593 void Frame::injectUserScriptsForWorld(DOMWrapperWorld* world, const UserScriptVector& userScripts, UserScriptInjectionTime injectionTime)
594 {
595     if (userScripts.isEmpty())
596         return;
597
598     Document* doc = document();
599     if (!doc)
600         return;
601
602     Vector<ScriptSourceCode> sourceCode;
603     unsigned count = userScripts.size();
604     for (unsigned i = 0; i < count; ++i) {
605         UserScript* script = userScripts[i].get();
606         if (script->injectedFrames() == InjectInTopFrameOnly && ownerElement())
607             continue;
608
609         if (script->injectionTime() == injectionTime && UserContentURLPattern::matchesPatterns(doc->url(), script->whitelist(), script->blacklist()))
610             m_script.evaluateInWorld(ScriptSourceCode(script->source(), script->url()), world);
611     }
612 }
613
614 bool Frame::shouldDeleteSelection(const VisibleSelection& selection) const
615 {
616     return editor()->client()->shouldDeleteRange(selection.toNormalizedRange().get());
617 }
618
619 bool Frame::isContentEditable() const
620 {
621     if (m_editor.clientIsEditable())
622         return true;
623     return m_doc->inDesignMode();
624 }
625
626 void Frame::setTypingStyle(CSSMutableStyleDeclaration *style)
627 {
628     m_typingStyle = style;
629 }
630
631 #ifndef NDEBUG
632 static HashSet<Frame*>& keepAliveSet()
633 {
634     DEFINE_STATIC_LOCAL(HashSet<Frame*>, staticKeepAliveSet, ());
635     return staticKeepAliveSet;
636 }
637 #endif
638
639 void Frame::keepAlive()
640 {
641     if (m_lifeSupportTimer.isActive())
642         return;
643 #ifndef NDEBUG
644     keepAliveSet().add(this);
645 #endif
646     ref();
647     m_lifeSupportTimer.startOneShot(0);
648 }
649
650 #ifndef NDEBUG
651 void Frame::cancelAllKeepAlive()
652 {
653     HashSet<Frame*>::iterator end = keepAliveSet().end();
654     for (HashSet<Frame*>::iterator it = keepAliveSet().begin(); it != end; ++it) {
655         Frame* frame = *it;
656         frame->m_lifeSupportTimer.stop();
657         frame->deref();
658     }
659     keepAliveSet().clear();
660 }
661 #endif
662
663 void Frame::lifeSupportTimerFired(Timer<Frame>*)
664 {
665 #ifndef NDEBUG
666     keepAliveSet().remove(this);
667 #endif
668     deref();
669 }
670
671 void Frame::clearDOMWindow()
672 {
673     if (m_domWindow) {
674         m_liveFormerWindows.add(m_domWindow.get());
675         m_domWindow->clear();
676     }
677     m_domWindow = 0;
678 }
679
680 RenderView* Frame::contentRenderer() const
681 {
682     Document* doc = document();
683     if (!doc)
684         return 0;
685     RenderObject* object = doc->renderer();
686     if (!object)
687         return 0;
688     ASSERT(object->isRenderView());
689     return toRenderView(object);
690 }
691
692 RenderPart* Frame::ownerRenderer() const
693 {
694     HTMLFrameOwnerElement* ownerElement = m_ownerElement;
695     if (!ownerElement)
696         return 0;
697     RenderObject* object = ownerElement->renderer();
698     if (!object)
699         return 0;
700     // FIXME: If <object> is ever fixed to disassociate itself from frames
701     // that it has started but canceled, then this can turn into an ASSERT
702     // since m_ownerElement would be 0 when the load is canceled.
703     // https://bugs.webkit.org/show_bug.cgi?id=18585
704     if (!object->isRenderPart())
705         return 0;
706     return toRenderPart(object);
707 }
708
709 // returns FloatRect because going through IntRect would truncate any floats
710 FloatRect Frame::selectionBounds(bool clipToVisibleContent) const
711 {
712     RenderView* root = contentRenderer();
713     FrameView* view = m_view.get();
714     if (!root || !view)
715         return IntRect();
716
717     IntRect selectionRect = root->selectionBounds(clipToVisibleContent);
718     return clipToVisibleContent ? intersection(selectionRect, view->visibleContentRect()) : selectionRect;
719 }
720
721 void Frame::selectionTextRects(Vector<FloatRect>& rects, SelectionRectRespectTransforms respectTransforms, bool clipToVisibleContent) const
722 {
723     RenderView* root = contentRenderer();
724     if (!root)
725         return;
726
727     RefPtr<Range> selectedRange = selection()->toNormalizedRange();
728
729     FloatRect visibleContentRect = m_view->visibleContentRect();
730     
731     // FIMXE: we are appending empty rects to the list for those that fall outside visibleContentRect.
732     // We may not want to do that.
733     if (respectTransforms) {
734         Vector<FloatQuad> quads;
735         selectedRange->textQuads(quads, true);
736
737         unsigned size = quads.size();
738         for (unsigned i = 0; i < size; ++i) {
739             IntRect currRect = quads[i].enclosingBoundingBox();
740             if (clipToVisibleContent)
741                 rects.append(intersection(currRect, visibleContentRect));
742             else
743                 rects.append(currRect);
744         }
745     } else {
746         Vector<IntRect> intRects;
747         selectedRange->textRects(intRects, true);
748
749         unsigned size = intRects.size();
750         for (unsigned i = 0; i < size; ++i) {
751             if (clipToVisibleContent)
752                 rects.append(intersection(intRects[i], visibleContentRect));
753             else
754                 rects.append(intRects[i]);
755         }
756     }
757 }
758
759 // Scans logically forward from "start", including any child frames
760 static HTMLFormElement *scanForForm(Node *start)
761 {
762     Node *n;
763     for (n = start; n; n = n->traverseNextNode()) {
764         if (n->hasTagName(formTag))
765             return static_cast<HTMLFormElement*>(n);
766         else if (n->isHTMLElement() && static_cast<Element*>(n)->isFormControlElement())
767             return static_cast<HTMLFormControlElement*>(n)->form();
768         else if (n->hasTagName(frameTag) || n->hasTagName(iframeTag)) {
769             Node *childDoc = static_cast<HTMLFrameElementBase*>(n)->contentDocument();
770             if (HTMLFormElement *frameResult = scanForForm(childDoc))
771                 return frameResult;
772         }
773     }
774     return 0;
775 }
776
777 // We look for either the form containing the current focus, or for one immediately after it
778 HTMLFormElement *Frame::currentForm() const
779 {
780     // start looking either at the active (first responder) node, or where the selection is
781     Node *start = m_doc ? m_doc->focusedNode() : 0;
782     if (!start)
783         start = selection()->start().node();
784
785     // try walking up the node tree to find a form element
786     Node *n;
787     for (n = start; n; n = n->parentNode()) {
788         if (n->hasTagName(formTag))
789             return static_cast<HTMLFormElement*>(n);
790         else if (n->isHTMLElement() && static_cast<Element*>(n)->isFormControlElement())
791             return static_cast<HTMLFormControlElement*>(n)->form();
792     }
793
794     // try walking forward in the node tree to find a form element
795     return start ? scanForForm(start) : 0;
796 }
797
798 void Frame::revealSelection(const ScrollAlignment& alignment, bool revealExtent)
799 {
800     IntRect rect;
801
802     switch (selection()->selectionType()) {
803     case VisibleSelection::NoSelection:
804         return;
805     case VisibleSelection::CaretSelection:
806         rect = selection()->absoluteCaretBounds();
807         break;
808     case VisibleSelection::RangeSelection:
809         rect = revealExtent ? VisiblePosition(selection()->extent()).absoluteCaretBounds() : enclosingIntRect(selectionBounds(false));
810         break;
811     }
812
813     Position start = selection()->start();
814     ASSERT(start.node());
815     if (start.node() && start.node()->renderer()) {
816         // FIXME: This code only handles scrolling the startContainer's layer, but
817         // the selection rect could intersect more than just that.
818         // See <rdar://problem/4799899>.
819         if (RenderLayer* layer = start.node()->renderer()->enclosingLayer()) {
820             layer->scrollRectToVisible(rect, false, alignment, alignment);
821             selection()->updateAppearance();
822         }
823     }
824 }
825
826 Frame* Frame::frameForWidget(const Widget* widget)
827 {
828     ASSERT_ARG(widget, widget);
829
830     if (RenderWidget* renderer = RenderWidget::find(widget))
831         if (Node* node = renderer->node())
832             return node->document()->frame();
833
834     // Assume all widgets are either a FrameView or owned by a RenderWidget.
835     // FIXME: That assumption is not right for scroll bars!
836     ASSERT(widget->isFrameView());
837     return static_cast<const FrameView*>(widget)->frame();
838 }
839
840 void Frame::clearTimers(FrameView *view, Document *document)
841 {
842     if (view) {
843         view->unscheduleRelayout();
844         if (view->frame()) {
845             view->frame()->animation()->suspendAnimations(document);
846             view->frame()->eventHandler()->stopAutoscrollTimer();
847         }
848     }
849 }
850
851 void Frame::clearTimers()
852 {
853     clearTimers(m_view.get(), document());
854 }
855
856 void Frame::setSelectionFromNone()
857 {
858     // Put a caret inside the body if the entire frame is editable (either the
859     // entire WebView is editable or designMode is on for this document).
860     Document *doc = document();
861     bool caretBrowsing = settings() && settings()->caretBrowsingEnabled();
862     if (!selection()->isNone() || !(isContentEditable() || caretBrowsing))
863         return;
864
865     Node* node = doc->documentElement();
866     while (node && !node->hasTagName(bodyTag))
867         node = node->traverseNextNode();
868     if (node)
869         selection()->setSelection(VisibleSelection(Position(node, 0), DOWNSTREAM));
870 }
871
872 void Frame::setDOMWindow(DOMWindow* domWindow)
873 {
874     if (m_domWindow) {
875         m_liveFormerWindows.add(m_domWindow.get());
876         m_domWindow->clear();
877     }
878     m_domWindow = domWindow;
879 }
880
881 DOMWindow* Frame::domWindow() const
882 {
883     if (!m_domWindow)
884         m_domWindow = DOMWindow::create(const_cast<Frame*>(this));
885
886     return m_domWindow.get();
887 }
888
889 void Frame::clearFormerDOMWindow(DOMWindow* window)
890 {
891     m_liveFormerWindows.remove(window);
892 }
893
894 void Frame::pageDestroyed()
895 {
896     if (Frame* parent = tree()->parent())
897         parent->loader()->checkLoadComplete();
898
899     if (m_domWindow)
900         m_domWindow->pageDestroyed();
901
902     // FIXME: It's unclear as to why this is called more than once, but it is,
903     // so page() could be NULL.
904     if (page() && page()->focusController()->focusedFrame() == this)
905         page()->focusController()->setFocusedFrame(0);
906
907     script()->clearWindowShell();
908     script()->clearScriptObjects();
909     script()->updatePlatformScriptObjects();
910
911     detachFromPage();
912 }
913
914 void Frame::disconnectOwnerElement()
915 {
916     if (m_ownerElement) {
917         if (Document* doc = document())
918             doc->clearAXObjectCache();
919         m_ownerElement->m_contentFrame = 0;
920         if (m_page)
921             m_page->decrementFrameCount();
922     }
923     m_ownerElement = 0;
924 }
925
926 // The frame is moved in DOM, potentially to another page.
927 void Frame::transferChildFrameToNewDocument()
928 {
929     ASSERT(m_ownerElement);
930     Frame* newParent = m_ownerElement->document()->frame();
931     bool didTransfer = false;
932
933     // Switch page.
934     Page* newPage = newParent ? newParent->page() : 0;
935     if (m_page != newPage) {
936         if (page()->focusController()->focusedFrame() == this)
937             page()->focusController()->setFocusedFrame(0);
938
939         if (m_page)
940             m_page->decrementFrameCount();
941
942         m_page = newPage;
943
944         if (newPage)
945             newPage->incrementFrameCount();
946
947         didTransfer = true;
948     }
949
950     // Update the frame tree.
951     Frame* oldParent = tree()->parent();
952     if (oldParent != newParent) {
953         if (oldParent)
954             oldParent->tree()->removeChild(this);
955         if (newParent) {
956             newParent->tree()->appendChild(this);
957             m_ownerElement->setName();
958         }
959         didTransfer = true;
960     }
961
962     // Avoid unnecessary calls to client and frame subtree if the frame ended
963     // up on the same page and under the same parent frame.
964     if (didTransfer) {
965         // Let external clients update themselves.
966         loader()->client()->didTransferChildFrameToNewDocument();
967
968         // Do the same for all the children.
969         for (Frame* child = tree()->firstChild(); child; child = child->tree()->nextSibling())
970             child->transferChildFrameToNewDocument();
971     }
972 }
973
974 String Frame::documentTypeString() const
975 {
976     if (DocumentType* doctype = document()->doctype())
977         return createMarkup(doctype);
978
979     return String();
980 }
981
982 bool Frame::shouldChangeSelection(const VisibleSelection& newSelection) const
983 {
984     return editor()->shouldChangeSelection(selection()->selection(), newSelection, newSelection.affinity(), false);
985 }
986
987 VisiblePosition Frame::visiblePositionForPoint(const IntPoint& framePoint)
988 {
989     HitTestResult result = eventHandler()->hitTestResultAtPoint(framePoint, true);
990     Node* node = result.innerNode();
991     if (!node)
992         return VisiblePosition();
993     RenderObject* renderer = node->renderer();
994     if (!renderer)
995         return VisiblePosition();
996     VisiblePosition visiblePos = renderer->positionForPoint(result.localPoint());
997     if (visiblePos.isNull())
998         visiblePos = VisiblePosition(Position(node, 0));
999     return visiblePos;
1000 }
1001
1002 Document* Frame::documentAtPoint(const IntPoint& point)
1003 {
1004     if (!view())
1005         return 0;
1006
1007     IntPoint pt = view()->windowToContents(point);
1008     HitTestResult result = HitTestResult(pt);
1009
1010     if (contentRenderer())
1011         result = eventHandler()->hitTestResultAtPoint(pt, false);
1012     return result.innerNode() ? result.innerNode()->document() : 0;
1013 }
1014
1015 void Frame::createView(const IntSize& viewportSize,
1016                        const Color& backgroundColor, bool transparent,
1017                        const IntSize& fixedLayoutSize, bool useFixedLayout,
1018                        ScrollbarMode horizontalScrollbarMode, bool horizontalLock,
1019                        ScrollbarMode verticalScrollbarMode, bool verticalLock)
1020 {
1021     ASSERT(this);
1022     ASSERT(m_page);
1023
1024     bool isMainFrame = this == m_page->mainFrame();
1025
1026     if (isMainFrame && view())
1027         view()->setParentVisible(false);
1028
1029     setView(0);
1030
1031     RefPtr<FrameView> frameView;
1032     if (isMainFrame) {
1033         frameView = FrameView::create(this, viewportSize);
1034         frameView->setFixedLayoutSize(fixedLayoutSize);
1035         frameView->setUseFixedLayout(useFixedLayout);
1036     } else
1037         frameView = FrameView::create(this);
1038
1039     frameView->setScrollbarModes(horizontalScrollbarMode, verticalScrollbarMode, horizontalLock, verticalLock);
1040
1041     setView(frameView);
1042
1043     if (backgroundColor.isValid())
1044         frameView->updateBackgroundRecursively(backgroundColor, transparent);
1045
1046     if (isMainFrame)
1047         frameView->setParentVisible(true);
1048
1049     if (ownerRenderer())
1050         ownerRenderer()->setWidget(frameView);
1051
1052     if (HTMLFrameOwnerElement* owner = ownerElement())
1053         view()->setCanHaveScrollbars(owner->scrollingMode() != ScrollbarAlwaysOff);
1054 }
1055
1056 #if ENABLE(TILED_BACKING_STORE)
1057 void Frame::setTiledBackingStoreEnabled(bool enabled)
1058 {
1059     if (!enabled) {
1060         m_tiledBackingStore.clear();
1061         return;
1062     }
1063     if (m_tiledBackingStore)
1064         return;
1065     m_tiledBackingStore.set(new TiledBackingStore(this));
1066     if (m_view)
1067         m_view->setPaintsEntireContents(true);
1068 }
1069
1070 void Frame::tiledBackingStorePaintBegin()
1071 {
1072     if (!m_view)
1073         return;
1074     m_view->updateLayoutAndStyleIfNeededRecursive();
1075     m_view->flushDeferredRepaints();
1076 }
1077
1078 void Frame::tiledBackingStorePaint(GraphicsContext* context, const IntRect& rect)
1079 {
1080     if (!m_view)
1081         return;
1082     m_view->paintContents(context, rect);
1083 }
1084
1085 void Frame::tiledBackingStorePaintEnd(const Vector<IntRect>& paintedArea)
1086 {
1087     if (!m_page || !m_view)
1088         return;
1089     unsigned size = paintedArea.size();
1090     // Request repaint from the system
1091     for (int n = 0; n < size; ++n)
1092         m_page->chrome()->invalidateContentsAndWindow(m_view->contentsToWindow(paintedArea[n]), false);
1093 }
1094
1095 IntRect Frame::tiledBackingStoreContentsRect()
1096 {
1097     if (!m_view)
1098         return IntRect();
1099     return IntRect(IntPoint(), m_view->contentsSize());
1100 }
1101
1102 IntRect Frame::tiledBackingStoreVisibleRect()
1103 {
1104     if (!m_page)
1105         return IntRect();
1106     return m_page->chrome()->client()->visibleRectForTiledBackingStore();
1107 }
1108 #endif
1109
1110 String Frame::layerTreeAsText() const
1111 {
1112 #if USE(ACCELERATED_COMPOSITING)
1113     document()->updateLayout();
1114
1115     if (!contentRenderer())
1116         return String();
1117
1118     RenderLayerCompositor* compositor = contentRenderer()->compositor();
1119     if (compositor->compositingLayerUpdatePending())
1120         compositor->updateCompositingLayers();
1121
1122     GraphicsLayer* rootLayer = compositor->rootPlatformLayer();
1123     if (!rootLayer)
1124         return String();
1125
1126     return rootLayer->layerTreeAsText();
1127 #else
1128     return String();
1129 #endif
1130 }
1131
1132 } // namespace WebCore