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