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