Source/WebCore: Remove Node::attached()
[WebKit-https.git] / Source / 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, 2011 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  * Copyright (C) 2008 Google Inc.
13  *
14  * This library is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU Library General Public
16  * License as published by the Free Software Foundation; either
17  * version 2 of the License, or (at your option) any later version.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  * Library General Public License for more details.
23  *
24  * You should have received a copy of the GNU Library General Public License
25  * along with this library; see the file COPYING.LIB.  If not, write to
26  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
27  * Boston, MA 02110-1301, USA.
28  */
29
30 #include "config.h"
31 #include "Frame.h"
32
33 #include "AnimationController.h"
34 #include "ApplyStyleCommand.h"
35 #include "BackForwardController.h"
36 #include "CSSComputedStyleDeclaration.h"
37 #include "CSSPropertyNames.h"
38 #include "CachedCSSStyleSheet.h"
39 #include "CachedResourceLoader.h"
40 #include "Chrome.h"
41 #include "ChromeClient.h"
42 #include "DOMWindow.h"
43 #include "DocumentType.h"
44 #include "Editor.h"
45 #include "EditorClient.h"
46 #include "Event.h"
47 #include "EventHandler.h"
48 #include "EventNames.h"
49 #include "FloatQuad.h"
50 #include "FocusController.h"
51 #include "FrameDestructionObserver.h"
52 #include "FrameLoader.h"
53 #include "FrameLoaderClient.h"
54 #include "FrameSelection.h"
55 #include "FrameView.h"
56 #include "GraphicsContext.h"
57 #include "GraphicsLayer.h"
58 #include "HTMLDocument.h"
59 #include "HTMLFormControlElement.h"
60 #include "HTMLFormElement.h"
61 #include "HTMLFrameElementBase.h"
62 #include "HTMLNames.h"
63 #include "HTMLTableCellElement.h"
64 #include "HitTestResult.h"
65 #include "ImageBuffer.h"
66 #include "InspectorInstrumentation.h"
67 #include "JSDOMWindowShell.h"
68 #include "Logging.h"
69 #include "MainFrame.h"
70 #include "MathMLNames.h"
71 #include "MediaFeatureNames.h"
72 #include "Navigator.h"
73 #include "NodeList.h"
74 #include "NodeTraversal.h"
75 #include "Page.h"
76 #include "PageCache.h"
77 #include "PageGroup.h"
78 #include "RegularExpression.h"
79 #include "RenderTableCell.h"
80 #include "RenderText.h"
81 #include "RenderTextControl.h"
82 #include "RenderTheme.h"
83 #include "RenderView.h"
84 #include "RenderWidget.h"
85 #include "RuntimeEnabledFeatures.h"
86 #include "SVGNames.h"
87 #include "ScriptController.h"
88 #include "ScriptSourceCode.h"
89 #include "ScrollingCoordinator.h"
90 #include "Settings.h"
91 #include "StyleProperties.h"
92 #include "TextIterator.h"
93 #include "TextNodeTraversal.h"
94 #include "TextResourceDecoder.h"
95 #include "UserContentURLPattern.h"
96 #include "UserTypingGestureIndicator.h"
97 #include "VisibleUnits.h"
98 #include "WebKitFontFamilyNames.h"
99 #include "XLinkNames.h"
100 #include "XMLNSNames.h"
101 #include "XMLNames.h"
102 #include "htmlediting.h"
103 #include "markup.h"
104 #include "npruntime_impl.h"
105 #include "runtime_root.h"
106 #include <bindings/ScriptValue.h>
107 #include <wtf/PassOwnPtr.h>
108 #include <wtf/RefCountedLeakCounter.h>
109 #include <wtf/StdLibExtras.h>
110
111 #if USE(ACCELERATED_COMPOSITING)
112 #include "RenderLayerCompositor.h"
113 #endif
114
115 #if ENABLE(SVG)
116 #include "SVGDocument.h"
117 #include "SVGDocumentExtensions.h"
118 #endif
119
120 #if USE(TILED_BACKING_STORE)
121 #include "TiledBackingStore.h"
122 #endif
123
124 #if PLATFORM(IOS)
125 #include "WKContentObservation.h"
126 #endif
127
128 namespace WebCore {
129
130 using namespace HTMLNames;
131
132 #if PLATFORM(IOS)
133 const unsigned scrollFrequency = 1000 / 60;
134 #endif
135
136 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, frameCounter, ("Frame"));
137
138 static inline Frame* parentFromOwnerElement(HTMLFrameOwnerElement* ownerElement)
139 {
140     if (!ownerElement)
141         return 0;
142     return ownerElement->document().frame();
143 }
144
145 static inline float parentPageZoomFactor(Frame* frame)
146 {
147     Frame* parent = frame->tree().parent();
148     if (!parent)
149         return 1;
150     return parent->pageZoomFactor();
151 }
152
153 static inline float parentTextZoomFactor(Frame* frame)
154 {
155     Frame* parent = frame->tree().parent();
156     if (!parent)
157         return 1;
158     return parent->textZoomFactor();
159 }
160
161 Frame::Frame(Page& page, HTMLFrameOwnerElement* ownerElement, FrameLoaderClient& frameLoaderClient)
162     : m_mainFrame(ownerElement ? page.mainFrame() : static_cast<MainFrame&>(*this))
163     , m_page(&page)
164     , m_settings(&page.settings())
165     , m_treeNode(this, parentFromOwnerElement(ownerElement))
166     , m_loader(*this, frameLoaderClient)
167     , m_navigationScheduler(this)
168     , m_ownerElement(ownerElement)
169     , m_script(std::make_unique<ScriptController>(*this))
170     , m_editor(Editor::create(*this))
171     , m_selection(adoptPtr(new FrameSelection(this)))
172     , m_eventHandler(adoptPtr(new EventHandler(*this)))
173     , m_animationController(std::make_unique<AnimationController>(*this))
174 #if PLATFORM(IOS)
175     , m_overflowAutoScrollTimer(this, &Frame::overflowAutoScrollTimerFired)
176     , m_selectionChangeCallbacksDisabled(false)
177     , m_timersPausedCount(0)
178 #endif
179     , m_pageZoomFactor(parentPageZoomFactor(this))
180     , m_textZoomFactor(parentTextZoomFactor(this))
181 #if ENABLE(ORIENTATION_EVENTS)
182     , m_orientation(0)
183 #endif
184     , m_inViewSourceMode(false)
185     , m_activeDOMObjectsAndAnimationsSuspendedCount(0)
186 {
187     AtomicString::init();
188     HTMLNames::init();
189     QualifiedName::init();
190     MediaFeatureNames::init();
191     SVGNames::init();
192     XLinkNames::init();
193     MathMLNames::init();
194     XMLNSNames::init();
195     XMLNames::init();
196     WebKitFontFamilyNames::init();
197
198     if (!ownerElement) {
199 #if USE(TILED_BACKING_STORE)
200         // Top level frame only for now.
201         setTiledBackingStoreEnabled(settings().tiledBackingStoreEnabled());
202 #endif
203     } else {
204         m_mainFrame.selfOnlyRef();
205         page.incrementSubframeCount();
206         ownerElement->setContentFrame(this);
207     }
208
209 #ifndef NDEBUG
210     frameCounter.increment();
211 #endif
212
213     // FIXME: We should reconcile the iOS and OpenSource code below.
214     Frame* parent = parentFromOwnerElement(ownerElement);
215 #if PLATFORM(IOS)
216     // Pause future timers if this frame is created when page is in pending state.
217     if (parent && parent->timersPaused())
218         setTimersPaused(true);
219 #else
220     // Pause future ActiveDOMObjects if this frame is being created while the page is in a paused state.
221     if (parent && parent->activeDOMObjectsAndAnimationsSuspended())
222         suspendActiveDOMObjectsAndAnimations();
223 #endif
224 }
225
226 PassRefPtr<Frame> Frame::create(Page* page, HTMLFrameOwnerElement* ownerElement, FrameLoaderClient* client)
227 {
228     ASSERT(page);
229     ASSERT(client);
230     return adoptRef(new Frame(*page, ownerElement, *client));
231 }
232
233 Frame::~Frame()
234 {
235     setView(0);
236     loader().cancelAndClear();
237
238     // FIXME: We should not be doing all this work inside the destructor
239
240 #ifndef NDEBUG
241     frameCounter.decrement();
242 #endif
243
244     disconnectOwnerElement();
245
246     for (auto& observer : m_destructionObservers)
247         observer->frameDestroyed();
248
249     if (!isMainFrame())
250         m_mainFrame.selfOnlyDeref();
251 }
252
253 void Frame::addDestructionObserver(FrameDestructionObserver* observer)
254 {
255     m_destructionObservers.add(observer);
256 }
257
258 void Frame::removeDestructionObserver(FrameDestructionObserver* observer)
259 {
260     m_destructionObservers.remove(observer);
261 }
262
263 void Frame::setView(PassRefPtr<FrameView> view)
264 {
265     // We the custom scroll bars as early as possible to prevent m_doc->detach()
266     // from messing with the view such that its scroll bars won't be torn down.
267     // FIXME: We should revisit this.
268     if (m_view)
269         m_view->prepareForDetach();
270
271     // Prepare for destruction now, so any unload event handlers get run and the DOMWindow is
272     // notified. If we wait until the view is destroyed, then things won't be hooked up enough for
273     // these calls to work.
274     if (!view && m_doc && m_doc->hasLivingRenderTree() && !m_doc->inPageCache())
275         m_doc->prepareForDestruction();
276     
277     if (m_view)
278         m_view->unscheduleRelayout();
279     
280     eventHandler().clear();
281
282     m_view = view;
283
284     // Only one form submission is allowed per view of a part.
285     // Since this part may be getting reused as a result of being
286     // pulled from the back/forward cache, reset this flag.
287     loader().resetMultipleFormSubmissionProtection();
288     
289 #if USE(TILED_BACKING_STORE)
290     if (m_view && tiledBackingStore())
291         m_view->setPaintsEntireContents(true);
292 #endif
293 }
294
295 void Frame::setDocument(PassRefPtr<Document> newDocument)
296 {
297     ASSERT(!newDocument || newDocument->frame() == this);
298
299     if (m_doc && m_doc->hasLivingRenderTree() && !m_doc->inPageCache())
300         m_doc->prepareForDestruction();
301
302     m_doc = newDocument.get();
303     ASSERT(!m_doc || m_doc->domWindow());
304     ASSERT(!m_doc || m_doc->domWindow()->frame() == this);
305
306     // Don't use m_doc because it can be overwritten and we want to guarantee
307     // that the document is not destroyed during this function call.
308     if (newDocument)
309         newDocument->didBecomeCurrentDocumentInFrame();
310 }
311
312 #if ENABLE(ORIENTATION_EVENTS)
313 void Frame::sendOrientationChangeEvent(int orientation)
314 {
315     m_orientation = orientation;
316     if (Document* doc = document())
317         doc->dispatchWindowEvent(Event::create(eventNames().orientationchangeEvent, false, false));
318 }
319 #endif // ENABLE(ORIENTATION_EVENTS)
320
321 static PassOwnPtr<RegularExpression> createRegExpForLabels(const Vector<String>& labels)
322 {
323     // REVIEW- version of this call in FrameMac.mm caches based on the NSArray ptrs being
324     // the same across calls.  We can't do that.
325
326     DEFINE_STATIC_LOCAL(RegularExpression, wordRegExp, ("\\w", TextCaseSensitive));
327     String pattern("(");
328     unsigned int numLabels = labels.size();
329     unsigned int i;
330     for (i = 0; i < numLabels; i++) {
331         String label = labels[i];
332
333         bool startsWithWordChar = false;
334         bool endsWithWordChar = false;
335         if (label.length()) {
336             startsWithWordChar = wordRegExp.match(label.substring(0, 1)) >= 0;
337             endsWithWordChar = wordRegExp.match(label.substring(label.length() - 1, 1)) >= 0;
338         }
339
340         if (i)
341             pattern.append("|");
342         // Search for word boundaries only if label starts/ends with "word characters".
343         // If we always searched for word boundaries, this wouldn't work for languages
344         // such as Japanese.
345         if (startsWithWordChar)
346             pattern.append("\\b");
347         pattern.append(label);
348         if (endsWithWordChar)
349             pattern.append("\\b");
350     }
351     pattern.append(")");
352     return adoptPtr(new RegularExpression(pattern, TextCaseInsensitive));
353 }
354
355 String Frame::searchForLabelsAboveCell(RegularExpression* regExp, HTMLTableCellElement* cell, size_t* resultDistanceFromStartOfCell)
356 {
357     HTMLTableCellElement* aboveCell = cell->cellAbove();
358     if (aboveCell) {
359         // search within the above cell we found for a match
360         size_t lengthSearched = 0;    
361         for (Text* textNode = TextNodeTraversal::firstWithin(aboveCell); textNode; textNode = TextNodeTraversal::next(textNode, aboveCell)) {
362             if (!textNode->renderer() || textNode->renderer()->style().visibility() != VISIBLE)
363                 continue;
364             // For each text chunk, run the regexp
365             String nodeString = textNode->data();
366             int pos = regExp->searchRev(nodeString);
367             if (pos >= 0) {
368                 if (resultDistanceFromStartOfCell)
369                     *resultDistanceFromStartOfCell = lengthSearched;
370                 return nodeString.substring(pos, regExp->matchedLength());
371             }
372             lengthSearched += nodeString.length();
373         }
374     }
375
376     // Any reason in practice to search all cells in that are above cell?
377     if (resultDistanceFromStartOfCell)
378         *resultDistanceFromStartOfCell = notFound;
379     return String();
380 }
381
382 String Frame::searchForLabelsBeforeElement(const Vector<String>& labels, Element* element, size_t* resultDistance, bool* resultIsInCellAbove)
383 {
384     OwnPtr<RegularExpression> regExp(createRegExpForLabels(labels));
385     // We stop searching after we've seen this many chars
386     const unsigned int charsSearchedThreshold = 500;
387     // This is the absolute max we search.  We allow a little more slop than
388     // charsSearchedThreshold, to make it more likely that we'll search whole nodes.
389     const unsigned int maxCharsSearched = 600;
390     // If the starting element is within a table, the cell that contains it
391     HTMLTableCellElement* startingTableCell = 0;
392     bool searchedCellAbove = false;
393
394     if (resultDistance)
395         *resultDistance = notFound;
396     if (resultIsInCellAbove)
397         *resultIsInCellAbove = false;
398     
399     // walk backwards in the node tree, until another element, or form, or end of tree
400     int unsigned lengthSearched = 0;
401     Node* n;
402     for (n = NodeTraversal::previous(element); n && lengthSearched < charsSearchedThreshold; n = NodeTraversal::previous(n)) {
403         // We hit another form element or the start of the form - bail out
404         if (isHTMLFormElement(n) || (n->isHTMLElement() && toElement(n)->isFormControlElement()))
405             break;
406
407         if (n->hasTagName(tdTag) && !startingTableCell) {
408             startingTableCell = toHTMLTableCellElement(n);
409         } else if (n->hasTagName(trTag) && startingTableCell) {
410             String result = searchForLabelsAboveCell(regExp.get(), startingTableCell, resultDistance);
411             if (!result.isEmpty()) {
412                 if (resultIsInCellAbove)
413                     *resultIsInCellAbove = true;
414                 return result;
415             }
416             searchedCellAbove = true;
417         } else if (n->isTextNode() && n->renderer() && n->renderer()->style().visibility() == VISIBLE) {
418             // For each text chunk, run the regexp
419             String nodeString = n->nodeValue();
420             // add 100 for slop, to make it more likely that we'll search whole nodes
421             if (lengthSearched + nodeString.length() > maxCharsSearched)
422                 nodeString = nodeString.right(charsSearchedThreshold - lengthSearched);
423             int pos = regExp->searchRev(nodeString);
424             if (pos >= 0) {
425                 if (resultDistance)
426                     *resultDistance = lengthSearched;
427                 return nodeString.substring(pos, regExp->matchedLength());
428             }
429             lengthSearched += nodeString.length();
430         }
431     }
432
433     // If we started in a cell, but bailed because we found the start of the form or the
434     // previous element, we still might need to search the row above us for a label.
435     if (startingTableCell && !searchedCellAbove) {
436          String result = searchForLabelsAboveCell(regExp.get(), startingTableCell, resultDistance);
437         if (!result.isEmpty()) {
438             if (resultIsInCellAbove)
439                 *resultIsInCellAbove = true;
440             return result;
441         }
442     }
443     return String();
444 }
445
446 static String matchLabelsAgainstString(const Vector<String>& labels, const String& stringToMatch)
447 {
448     if (stringToMatch.isEmpty())
449         return String();
450
451     String mutableStringToMatch = stringToMatch;
452
453     // Make numbers and _'s in field names behave like word boundaries, e.g., "address2"
454     replace(mutableStringToMatch, RegularExpression("\\d", TextCaseSensitive), " ");
455     mutableStringToMatch.replace('_', ' ');
456     
457     OwnPtr<RegularExpression> regExp(createRegExpForLabels(labels));
458     // Use the largest match we can find in the whole string
459     int pos;
460     int length;
461     int bestPos = -1;
462     int bestLength = -1;
463     int start = 0;
464     do {
465         pos = regExp->match(mutableStringToMatch, start);
466         if (pos != -1) {
467             length = regExp->matchedLength();
468             if (length >= bestLength) {
469                 bestPos = pos;
470                 bestLength = length;
471             }
472             start = pos + 1;
473         }
474     } while (pos != -1);
475     
476     if (bestPos != -1)
477         return mutableStringToMatch.substring(bestPos, bestLength);
478     return String();
479 }
480     
481 String Frame::matchLabelsAgainstElement(const Vector<String>& labels, Element* element)
482 {
483     // Match against the name element, then against the id element if no match is found for the name element.
484     // See 7538330 for one popular site that benefits from the id element check.
485     // FIXME: This code is mirrored in FrameMac.mm. It would be nice to make the Mac code call the platform-agnostic
486     // code, which would require converting the NSArray of NSStrings to a Vector of Strings somewhere along the way.
487     String resultFromNameAttribute = matchLabelsAgainstString(labels, element->getNameAttribute());
488     if (!resultFromNameAttribute.isEmpty())
489         return resultFromNameAttribute;
490     
491     return matchLabelsAgainstString(labels, element->getAttribute(idAttr));
492 }
493
494 #if PLATFORM(IOS)
495 void Frame::scrollOverflowLayer(RenderLayer* layer, const IntRect& visibleRect, const IntRect& exposeRect)
496 {
497     if (!layer)
498         return;
499
500     RenderBox* box = layer->renderBox();
501     if (!box)
502         return;
503
504     if (visibleRect.intersects(exposeRect))
505         return;
506
507     int x = layer->scrollXOffset();
508     int exposeLeft = exposeRect.x();
509     int exposeRight = exposeLeft + exposeRect.width();
510     int clientWidth = box->clientWidth();
511     if (exposeLeft <= 0)
512         x = std::max(0, x + exposeLeft - clientWidth / 2);
513     else if (exposeRight >= clientWidth)
514         x = std::min(box->scrollWidth() - clientWidth, x + clientWidth / 2);
515
516     int y = layer->scrollYOffset();
517     int exposeTop = exposeRect.y();
518     int exposeBottom = exposeTop + exposeRect.height();
519     int clientHeight = box->clientHeight();
520     if (exposeTop <= 0)
521         y = std::max(0, y + exposeTop - clientHeight / 2);
522     else if (exposeBottom >= clientHeight)
523         y = std::min(box->scrollHeight() - clientHeight, y + clientHeight / 2);
524
525     layer->scrollToOffset(IntSize(x, y));
526     selection().setCaretRectNeedsUpdate();
527     selection().updateAppearance();
528 }
529
530 void Frame::overflowAutoScrollTimerFired(Timer<Frame>*)
531 {
532     if (!eventHandler().mousePressed() || checkOverflowScroll(PerformOverflowScroll) == OverflowScrollNone) {
533         if (m_overflowAutoScrollTimer.isActive())
534             m_overflowAutoScrollTimer.stop();
535     }
536 }
537
538 void Frame::startOverflowAutoScroll(const IntPoint& mousePosition)
539 {
540     m_overflowAutoScrollPos = mousePosition;
541
542     if (m_overflowAutoScrollTimer.isActive())
543         return;
544
545     if (checkOverflowScroll(DoNotPerformOverflowScroll) == OverflowScrollNone)
546         return;
547
548     m_overflowAutoScrollTimer.startRepeating(scrollFrequency);
549     m_overflowAutoScrollDelta = 3;
550 }
551
552 int Frame::checkOverflowScroll(OverflowScrollAction action)
553 {
554     Position extent = selection().selection().extent();
555     if (extent.isNull())
556         return OverflowScrollNone;
557
558     RenderObject* renderer = extent.deprecatedNode()->renderer();
559     if (!renderer)
560         return OverflowScrollNone;
561
562     FrameView* view = this->view();
563     if (!view)
564         return OverflowScrollNone;
565
566     RenderBlock* containingBlock = renderer->containingBlock();
567     if (!containingBlock || !containingBlock->hasOverflowClip())
568         return OverflowScrollNone;
569     RenderLayer* layer = containingBlock->layer();
570     ASSERT(layer);
571
572     IntRect visibleRect = IntRect(view->scrollX(), view->scrollY(), view->visibleWidth(), view->visibleHeight());
573     IntPoint position = m_overflowAutoScrollPos;
574     if (visibleRect.contains(position.x(), position.y()))
575         return OverflowScrollNone;
576
577     int scrollType = 0;
578     int deltaX = 0;
579     int deltaY = 0;
580     IntPoint selectionPosition;
581
582     // This constant will make the selection draw a little bit beyond the edge of the visible area.
583     // This prevents a visual glitch, in that you can fail to select a portion of a character that
584     // is being rendered right at the edge of the visible rectangle.
585     // FIXME: This probably needs improvement, and may need to take the font size into account.
586     static const int scrollBoundsAdjustment = 3;
587
588     // FIXME: Make a small buffer at the end of a visible rectangle so that autoscrolling works 
589     // even if the visible extends to the limits of the screen.
590     if (position.x() < visibleRect.x()) {
591         scrollType |= OverflowScrollLeft;
592         if (action == PerformOverflowScroll) {
593             deltaX -= static_cast<int>(m_overflowAutoScrollDelta);
594             selectionPosition.setX(view->scrollX() - scrollBoundsAdjustment);
595         }
596     } else if (position.x() > visibleRect.maxX()) {
597         scrollType |= OverflowScrollRight;
598         if (action == PerformOverflowScroll) {
599             deltaX += static_cast<int>(m_overflowAutoScrollDelta);
600             selectionPosition.setX(view->scrollX() + view->visibleWidth() + scrollBoundsAdjustment);
601         }
602     }
603
604     if (position.y() < visibleRect.y()) {
605         scrollType |= OverflowScrollUp;
606         if (action == PerformOverflowScroll) {
607             deltaY -= static_cast<int>(m_overflowAutoScrollDelta);
608             selectionPosition.setY(view->scrollY() - scrollBoundsAdjustment);
609         }
610     } else if (position.y() > visibleRect.maxY()) {
611         scrollType |= OverflowScrollDown;
612         if (action == PerformOverflowScroll) {
613             deltaY += static_cast<int>(m_overflowAutoScrollDelta);
614             selectionPosition.setY(view->scrollY() + view->visibleHeight() + scrollBoundsAdjustment);
615         }
616     }
617
618     if (action == PerformOverflowScroll && (deltaX || deltaY)) {
619         layer->scrollToOffset(IntSize(layer->scrollXOffset() + deltaX, layer->scrollYOffset() + deltaY));
620
621         // Handle making selection.
622         VisiblePosition visiblePosition(renderer->positionForPoint(selectionPosition));
623         if (visiblePosition.isNotNull()) {
624             VisibleSelection visibleSelection = selection().selection();
625             visibleSelection.setExtent(visiblePosition);
626             if (selection().granularity() != CharacterGranularity)
627                 visibleSelection.expandUsingGranularity(selection().granularity());
628             if (selection().shouldChangeSelection(visibleSelection))
629                 selection().setSelection(visibleSelection);
630         }
631
632         m_overflowAutoScrollDelta *= 1.02f; // Accelerate the scroll
633     }
634     return scrollType;
635 }
636
637 void Frame::setSelectionChangeCallbacksDisabled(bool selectionChangeCallbacksDisabled)
638 {
639     m_selectionChangeCallbacksDisabled = selectionChangeCallbacksDisabled;
640 }
641
642 bool Frame::selectionChangeCallbacksDisabled() const
643 {
644     return m_selectionChangeCallbacksDisabled;
645 }
646 #endif // PLATFORM(IOS)
647
648 void Frame::setPrinting(bool printing, const FloatSize& pageSize, const FloatSize& originalPageSize, float maximumShrinkRatio, AdjustViewSizeOrNot shouldAdjustViewSize)
649 {
650     // In setting printing, we should not validate resources already cached for the document.
651     // See https://bugs.webkit.org/show_bug.cgi?id=43704
652     ResourceCacheValidationSuppressor validationSuppressor(m_doc->cachedResourceLoader());
653
654     m_doc->setPrinting(printing);
655     view()->adjustMediaTypeForPrinting(printing);
656
657     m_doc->styleResolverChanged(RecalcStyleImmediately);
658     if (shouldUsePrintingLayout()) {
659         view()->forceLayoutForPagination(pageSize, originalPageSize, maximumShrinkRatio, shouldAdjustViewSize);
660     } else {
661         view()->forceLayout();
662         if (shouldAdjustViewSize == AdjustViewSize)
663             view()->adjustViewSize();
664     }
665
666     // Subframes of the one we're printing don't lay out to the page size.
667     for (RefPtr<Frame> child = tree().firstChild(); child; child = child->tree().nextSibling())
668         child->setPrinting(printing, FloatSize(), FloatSize(), 0, shouldAdjustViewSize);
669 }
670
671 bool Frame::shouldUsePrintingLayout() const
672 {
673     // Only top frame being printed should be fit to page size.
674     // Subframes should be constrained by parents only.
675     return m_doc->printing() && (!tree().parent() || !tree().parent()->m_doc->printing());
676 }
677
678 FloatSize Frame::resizePageRectsKeepingRatio(const FloatSize& originalSize, const FloatSize& expectedSize)
679 {
680     FloatSize resultSize;
681     if (!contentRenderer())
682         return FloatSize();
683
684     if (contentRenderer()->style().isHorizontalWritingMode()) {
685         ASSERT(fabs(originalSize.width()) > std::numeric_limits<float>::epsilon());
686         float ratio = originalSize.height() / originalSize.width();
687         resultSize.setWidth(floorf(expectedSize.width()));
688         resultSize.setHeight(floorf(resultSize.width() * ratio));
689     } else {
690         ASSERT(fabs(originalSize.height()) > std::numeric_limits<float>::epsilon());
691         float ratio = originalSize.width() / originalSize.height();
692         resultSize.setHeight(floorf(expectedSize.height()));
693         resultSize.setWidth(floorf(resultSize.height() * ratio));
694     }
695     return resultSize;
696 }
697
698 void Frame::injectUserScripts(UserScriptInjectionTime injectionTime)
699 {
700     if (!m_page)
701         return;
702
703     if (loader().stateMachine()->creatingInitialEmptyDocument() && !settings().shouldInjectUserScriptsInInitialEmptyDocument())
704         return;
705
706     // Walk the hashtable. Inject by world.
707     const UserScriptMap* userScripts = m_page->group().userScripts();
708     if (!userScripts)
709         return;
710
711     for (auto it = userScripts->begin(), end = userScripts->end(); it != end; ++it)
712         injectUserScriptsForWorld(*it->key.get(), *it->value, injectionTime);
713 }
714
715 void Frame::injectUserScriptsForWorld(DOMWrapperWorld& world, const UserScriptVector& userScripts, UserScriptInjectionTime injectionTime)
716 {
717     if (userScripts.isEmpty())
718         return;
719
720     Document* doc = document();
721     if (!doc)
722         return;
723
724     Vector<ScriptSourceCode> sourceCode;
725     unsigned count = userScripts.size();
726     for (unsigned i = 0; i < count; ++i) {
727         UserScript* script = userScripts[i].get();
728         if (script->injectedFrames() == InjectInTopFrameOnly && ownerElement())
729             continue;
730
731         if (script->injectionTime() == injectionTime && UserContentURLPattern::matchesPatterns(doc->url(), script->whitelist(), script->blacklist()))
732             m_script->evaluateInWorld(ScriptSourceCode(script->source(), script->url()), world);
733     }
734 }
735
736 RenderView* Frame::contentRenderer() const
737 {
738     return document() ? document()->renderView() : 0;
739 }
740
741 RenderWidget* Frame::ownerRenderer() const
742 {
743     HTMLFrameOwnerElement* ownerElement = m_ownerElement;
744     if (!ownerElement)
745         return 0;
746     auto object = ownerElement->renderer();
747     if (!object)
748         return 0;
749     // FIXME: If <object> is ever fixed to disassociate itself from frames
750     // that it has started but canceled, then this can turn into an ASSERT
751     // since m_ownerElement would be 0 when the load is canceled.
752     // https://bugs.webkit.org/show_bug.cgi?id=18585
753     if (!object->isWidget())
754         return 0;
755     return toRenderWidget(object);
756 }
757
758 Frame* Frame::frameForWidget(const Widget* widget)
759 {
760     ASSERT_ARG(widget, widget);
761
762     if (RenderWidget* renderer = RenderWidget::find(widget))
763         return renderer->frameOwnerElement().document().frame();
764
765     // Assume all widgets are either a FrameView or owned by a RenderWidget.
766     // FIXME: That assumption is not right for scroll bars!
767     ASSERT_WITH_SECURITY_IMPLICATION(widget->isFrameView());
768     return &toFrameView(widget)->frame();
769 }
770
771 void Frame::clearTimers(FrameView *view, Document *document)
772 {
773     if (view) {
774         view->unscheduleRelayout();
775         view->frame().animation().suspendAnimationsForDocument(document);
776         view->frame().eventHandler().stopAutoscrollTimer();
777     }
778 }
779
780 void Frame::clearTimers()
781 {
782     clearTimers(m_view.get(), document());
783 }
784
785 void Frame::willDetachPage()
786 {
787     if (Frame* parent = tree().parent())
788         parent->loader().checkLoadComplete();
789
790     for (auto& observer : m_destructionObservers)
791         observer->willDetachPage();
792
793     // FIXME: It's unclear as to why this is called more than once, but it is,
794     // so page() could be NULL.
795     if (page() && page()->focusController().focusedFrame() == this)
796         page()->focusController().setFocusedFrame(0);
797
798     if (page() && page()->scrollingCoordinator() && m_view)
799         page()->scrollingCoordinator()->willDestroyScrollableArea(m_view.get());
800
801 #if PLATFORM(IOS)
802     if (WebThreadCountOfObservedContentModifiers() > 0 && m_page)
803         m_page->chrome().client().clearContentChangeObservers(this);
804 #endif
805
806     script().clearScriptObjects();
807     script().updatePlatformScriptObjects();
808 }
809
810 void Frame::disconnectOwnerElement()
811 {
812     if (m_ownerElement) {
813         // We use the ownerElement's document to retrieve the cache, because the contentDocument for this
814         // frame is already detached (and can't access the top level AX cache).
815         // However, we pass in the current document to clearTextMarkerNodesInUse so we can identify the
816         // nodes inside this document that need to be removed from the cache.
817         
818         // We don't clear the AXObjectCache here because we don't want to clear the top level cache
819         // when a sub-frame is removed.
820 #if HAVE(ACCESSIBILITY)
821         if (AXObjectCache* cache = m_ownerElement->document().existingAXObjectCache())
822             cache->clearTextMarkerNodesInUse(document());
823 #endif
824         
825         m_ownerElement->clearContentFrame();
826         if (m_page)
827             m_page->decrementSubframeCount();
828     }
829     m_ownerElement = nullptr;
830 }
831
832 String Frame::displayStringModifiedByEncoding(const String& str) const
833 {
834     return document() ? document()->displayStringModifiedByEncoding(str) : str;
835 }
836
837 VisiblePosition Frame::visiblePositionForPoint(const IntPoint& framePoint)
838 {
839     HitTestResult result = eventHandler().hitTestResultAtPoint(framePoint, HitTestRequest::ReadOnly | HitTestRequest::Active);
840     Node* node = result.innerNonSharedNode();
841     if (!node)
842         return VisiblePosition();
843     auto renderer = node->renderer();
844     if (!renderer)
845         return VisiblePosition();
846     VisiblePosition visiblePos = renderer->positionForPoint(result.localPoint());
847     if (visiblePos.isNull())
848         visiblePos = firstPositionInOrBeforeNode(node);
849     return visiblePos;
850 }
851
852 Document* Frame::documentAtPoint(const IntPoint& point)
853 {
854     if (!view())
855         return 0;
856
857     IntPoint pt = view()->windowToContents(point);
858     HitTestResult result = HitTestResult(pt);
859
860     if (contentRenderer())
861         result = eventHandler().hitTestResultAtPoint(pt);
862     return result.innerNode() ? &result.innerNode()->document() : 0;
863 }
864
865 PassRefPtr<Range> Frame::rangeForPoint(const IntPoint& framePoint)
866 {
867     VisiblePosition position = visiblePositionForPoint(framePoint);
868     if (position.isNull())
869         return 0;
870
871     VisiblePosition previous = position.previous();
872     if (previous.isNotNull()) {
873         RefPtr<Range> previousCharacterRange = makeRange(previous, position);
874         LayoutRect rect = editor().firstRectForRange(previousCharacterRange.get());
875         if (rect.contains(framePoint))
876             return previousCharacterRange.release();
877     }
878
879     VisiblePosition next = position.next();
880     if (RefPtr<Range> nextCharacterRange = makeRange(position, next)) {
881         LayoutRect rect = editor().firstRectForRange(nextCharacterRange.get());
882         if (rect.contains(framePoint))
883             return nextCharacterRange.release();
884     }
885
886     return 0;
887 }
888
889 void Frame::createView(const IntSize& viewportSize, const Color& backgroundColor, bool transparent,
890     const IntSize& fixedLayoutSize, const IntRect& fixedVisibleContentRect,
891     bool useFixedLayout, ScrollbarMode horizontalScrollbarMode, bool horizontalLock,
892     ScrollbarMode verticalScrollbarMode, bool verticalLock)
893 {
894     ASSERT(this);
895     ASSERT(m_page);
896
897     bool isMainFrame = this->isMainFrame();
898
899     if (isMainFrame && view())
900         view()->setParentVisible(false);
901
902     setView(0);
903
904     RefPtr<FrameView> frameView;
905     if (isMainFrame) {
906         frameView = FrameView::create(*this, viewportSize);
907         frameView->setFixedLayoutSize(fixedLayoutSize);
908 #if !PLATFORM(IOS)
909         frameView->setFixedVisibleContentRect(fixedVisibleContentRect);
910 #else
911         UNUSED_PARAM(fixedVisibleContentRect);
912 #endif
913         frameView->setUseFixedLayout(useFixedLayout);
914     } else
915         frameView = FrameView::create(*this);
916
917     frameView->setScrollbarModes(horizontalScrollbarMode, verticalScrollbarMode, horizontalLock, verticalLock);
918
919     setView(frameView);
920
921     if (backgroundColor.isValid())
922         frameView->updateBackgroundRecursively(backgroundColor, transparent);
923
924     if (isMainFrame)
925         frameView->setParentVisible(true);
926
927     if (ownerRenderer())
928         ownerRenderer()->setWidget(frameView);
929
930     if (HTMLFrameOwnerElement* owner = ownerElement())
931         view()->setCanHaveScrollbars(owner->scrollingMode() != ScrollbarAlwaysOff);
932 }
933
934 #if USE(TILED_BACKING_STORE)
935 void Frame::setTiledBackingStoreEnabled(bool enabled)
936 {
937     if (!enabled) {
938         m_tiledBackingStore.clear();
939         return;
940     }
941     if (m_tiledBackingStore)
942         return;
943     m_tiledBackingStore = adoptPtr(new TiledBackingStore(this));
944     m_tiledBackingStore->setCommitTileUpdatesOnIdleEventLoop(true);
945     if (m_view)
946         m_view->setPaintsEntireContents(true);
947 }
948
949 void Frame::tiledBackingStorePaintBegin()
950 {
951     if (!m_view)
952         return;
953     m_view->updateLayoutAndStyleIfNeededRecursive();
954     m_view->flushDeferredRepaints();
955 }
956
957 void Frame::tiledBackingStorePaint(GraphicsContext* context, const IntRect& rect)
958 {
959     if (!m_view)
960         return;
961     m_view->paintContents(context, rect);
962 }
963
964 void Frame::tiledBackingStorePaintEnd(const Vector<IntRect>& paintedArea)
965 {
966     if (!m_page || !m_view)
967         return;
968     unsigned size = paintedArea.size();
969     // Request repaint from the system
970     for (unsigned n = 0; n < size; ++n)
971         m_page->chrome().invalidateContentsAndRootView(m_view->contentsToRootView(paintedArea[n]), false);
972 }
973
974 IntRect Frame::tiledBackingStoreContentsRect()
975 {
976     if (!m_view)
977         return IntRect();
978     return IntRect(IntPoint(), m_view->contentsSize());
979 }
980
981 IntRect Frame::tiledBackingStoreVisibleRect()
982 {
983     if (!m_page)
984         return IntRect();
985     return m_page->chrome().client().visibleRectForTiledBackingStore();
986 }
987
988 Color Frame::tiledBackingStoreBackgroundColor() const
989 {
990     if (!m_view)
991         return Color();
992     return m_view->baseBackgroundColor();
993 }
994 #endif
995
996 String Frame::layerTreeAsText(LayerTreeFlags flags) const
997 {
998 #if USE(ACCELERATED_COMPOSITING)
999     document()->updateLayout();
1000
1001     if (!contentRenderer())
1002         return String();
1003
1004     return contentRenderer()->compositor().layerTreeAsText(flags);
1005 #else
1006     UNUSED_PARAM(flags);
1007     return String();
1008 #endif
1009 }
1010
1011 String Frame::trackedRepaintRectsAsText() const
1012 {
1013     if (!m_view)
1014         return String();
1015     return m_view->trackedRepaintRectsAsText();
1016 }
1017
1018 void Frame::setPageZoomFactor(float factor)
1019 {
1020     setPageAndTextZoomFactors(factor, m_textZoomFactor);
1021 }
1022
1023 void Frame::setTextZoomFactor(float factor)
1024 {
1025     setPageAndTextZoomFactors(m_pageZoomFactor, factor);
1026 }
1027
1028 void Frame::setPageAndTextZoomFactors(float pageZoomFactor, float textZoomFactor)
1029 {
1030     if (m_pageZoomFactor == pageZoomFactor && m_textZoomFactor == textZoomFactor)
1031         return;
1032
1033     Page* page = this->page();
1034     if (!page)
1035         return;
1036
1037     Document* document = this->document();
1038     if (!document)
1039         return;
1040
1041     m_editor->dismissCorrectionPanelAsIgnored();
1042
1043 #if ENABLE(SVG)
1044     // Respect SVGs zoomAndPan="disabled" property in standalone SVG documents.
1045     // FIXME: How to handle compound documents + zoomAndPan="disabled"? Needs SVG WG clarification.
1046     if (document->isSVGDocument()) {
1047         if (!toSVGDocument(document)->zoomAndPanEnabled())
1048             return;
1049     }
1050 #endif
1051
1052     if (m_pageZoomFactor != pageZoomFactor) {
1053         if (FrameView* view = this->view()) {
1054             // Update the scroll position when doing a full page zoom, so the content stays in relatively the same position.
1055             LayoutPoint scrollPosition = view->scrollPosition();
1056             float percentDifference = (pageZoomFactor / m_pageZoomFactor);
1057             view->setScrollPosition(IntPoint(scrollPosition.x() * percentDifference, scrollPosition.y() * percentDifference));
1058         }
1059     }
1060
1061     m_pageZoomFactor = pageZoomFactor;
1062     m_textZoomFactor = textZoomFactor;
1063
1064     document->recalcStyle(Style::Force);
1065
1066     for (RefPtr<Frame> child = tree().firstChild(); child; child = child->tree().nextSibling())
1067         child->setPageAndTextZoomFactors(m_pageZoomFactor, m_textZoomFactor);
1068
1069     if (FrameView* view = this->view()) {
1070         if (document->renderView() && document->renderView()->needsLayout() && view->didFirstLayout())
1071             view->layout();
1072     }
1073
1074     if (isMainFrame())
1075         pageCache()->markPagesForFullStyleRecalc(page);
1076 }
1077
1078 float Frame::frameScaleFactor() const
1079 {
1080     Page* page = this->page();
1081
1082     // Main frame is scaled with respect to he container but inner frames are not scaled with respect to the main frame.
1083     if (!page || &page->mainFrame() != this || settings().delegatesPageScaling())
1084         return 1;
1085
1086     return page->pageScaleFactor();
1087 }
1088
1089 void Frame::suspendActiveDOMObjectsAndAnimations()
1090 {
1091     bool wasSuspended = activeDOMObjectsAndAnimationsSuspended();
1092
1093     m_activeDOMObjectsAndAnimationsSuspendedCount++;
1094
1095     if (wasSuspended)
1096         return;
1097
1098     // FIXME: Suspend/resume calls will not match if the frame is navigated, and gets a new document.
1099     if (document()) {
1100         document()->suspendScriptedAnimationControllerCallbacks();
1101         animation().suspendAnimationsForDocument(document());
1102         document()->suspendActiveDOMObjects(ActiveDOMObject::PageWillBeSuspended);
1103     }
1104 }
1105
1106 void Frame::resumeActiveDOMObjectsAndAnimations()
1107 {
1108     ASSERT(activeDOMObjectsAndAnimationsSuspended());
1109
1110     m_activeDOMObjectsAndAnimationsSuspendedCount--;
1111
1112     if (activeDOMObjectsAndAnimationsSuspended())
1113         return;
1114
1115     if (document()) {
1116         document()->resumeActiveDOMObjects(ActiveDOMObject::PageWillBeSuspended);
1117         animation().resumeAnimationsForDocument(document());
1118         document()->resumeScriptedAnimationControllerCallbacks();
1119     }
1120 }
1121
1122 #if USE(ACCELERATED_COMPOSITING)
1123 void Frame::deviceOrPageScaleFactorChanged()
1124 {
1125     for (RefPtr<Frame> child = tree().firstChild(); child; child = child->tree().nextSibling())
1126         child->deviceOrPageScaleFactorChanged();
1127
1128     if (RenderView* root = contentRenderer())
1129         root->compositor().deviceOrPageScaleFactorChanged();
1130 }
1131 #endif
1132
1133 bool Frame::isURLAllowed(const URL& url) const
1134 {
1135     // We allow one level of self-reference because some sites depend on that,
1136     // but we don't allow more than one.
1137     if (m_page->subframeCount() >= Page::maxNumberOfFrames)
1138         return false;
1139     bool foundSelfReference = false;
1140     for (const Frame* frame = this; frame; frame = frame->tree().parent()) {
1141         if (equalIgnoringFragmentIdentifier(frame->document()->url(), url)) {
1142             if (foundSelfReference)
1143                 return false;
1144             foundSelfReference = true;
1145         }
1146     }
1147     return true;
1148 }
1149
1150 } // namespace WebCore